我正在嘗試posix_openpt在 Mac 上使用。我看到的問題是我從posix_openpt. 我使用檔案描述符讀取并使用dup寫入創建副本。我遇到的問題是,當我寫入主檔案描述符時,我從主檔案中讀回了該資料。所以沒有資料最終到達從站。我通過使用posix_spawnp運行一個將 stdin/stdout/stderr 設定為從檔案的程式來確認這一點。程式無限期掛起等待輸入。這是我的代碼(注意,為了易讀性,所有錯誤處理都被洗掉了):
int master_fd = posix_openpt(O_RDWR);
grantpt(master_fd);
unlockpt(master_fd);
char *slave_filename_orig = ptsname(master_fd);
size_t slave_filename_len = strlen(slave_filename_orig);
char slave_filename[slave_filename_len 1];
strcpy(slave_filename, slave_filename_orig);
posix_spawn_file_actions_t fd_actions;
posix_spawn_file_actions_init(&fd_actions);
posix_spawn_file_actions_addopen(&fd_actions, STDIN_FILENO, slave_filename, O_RDONLY, 0644);
posix_spawn_file_actions_addopen(&fd_actions, STDOUT_FILENO, slave_filename, O_WRONLY, 0644);
posix_spawn_file_actions_adddup2(&fd_actions, STDOUT_FILENO, STDERR_FILENO);
pid_t pid;
posix_spawnp(&pid, "wc", &fd_actions, NULL, NULL, NULL);
int master_fd_write = dup(master_fd);
char *data = "hello world";
write(master_fd_write, data, strlen(data));
close(master_fd_write);
char buffer[1024];
read(master_fd, buffer, 1024); // <- Issue Here
// buffer now contains hello world. It should contain the output of `wc`
uj5u.com熱心網友回復:
(注意:以上僅在 Linux 上測驗過;我沒有 Mac 可以使用,但我沒有理由相信這里的細節有什么不同。)
您的代碼有幾個問題:
至少在 Linux 上,posix_spawn()使用空指標呼叫會導致崩潰。您需要提供所有引數。即使 Mac 以您的方式接受它,這樣做也是一個好主意。
接下來,wc從標準輸入讀取將等到嘗試讀取更多資料給出檔案結束條件,然后列印出它收集的統計資訊;你的代碼不這樣做。對于 pty,如果您向其寫入特定位元組(通常值為 4,但它可能不同,因此最好使用終端所說的而不是硬編碼),終端驅動程式將識別為信號 EOF 而無需像使用管道時一樣關閉主服務器(使其無法讀取 的輸出wc)。
二、終端的默認設定包括回顯輸入;這就是你正在閱讀的內容。
一個解決了這些問題以及更多問題的清理版本(就像你的一樣,省略了大多數錯誤檢查;真正的代碼應該檢查所有這些函式是否有錯誤):
#define _XOPEN_SOURCE 700
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <spawn.h>
#include <termios.h>
#include <unistd.h>
#include <wait.h>
int main(void) {
int master_fd = posix_openpt(O_RDWR);
grantpt(master_fd);
unlockpt(master_fd);
char *slave_filename_orig = ptsname(master_fd);
size_t slave_filename_len = strlen(slave_filename_orig);
char slave_filename[slave_filename_len 1];
strcpy(slave_filename, slave_filename_orig);
//printf("slave pty filename: %s\n", slave_filename);
// Open the slave pty in this process
int slave_fd = open(slave_filename, O_RDWR);
// Set up slave pty to not echo input
struct termios tty_attrs;
tcgetattr(slave_fd, &tty_attrs);
tty_attrs.c_lflag &= ~ECHO;
tcsetattr(slave_fd, TCSANOW, &tty_attrs);
posix_spawn_file_actions_t fd_actions;
posix_spawn_file_actions_init(&fd_actions);
// Use adddup2 instead of addopen since we already have the pty open.
posix_spawn_file_actions_adddup2(&fd_actions, slave_fd, STDIN_FILENO);
posix_spawn_file_actions_adddup2(&fd_actions, slave_fd, STDOUT_FILENO);
// Also close the master and original slave fd in the child
posix_spawn_file_actions_addclose(&fd_actions, master_fd);
posix_spawn_file_actions_addclose(&fd_actions, slave_fd);
posix_spawnattr_t attrs;
posix_spawnattr_init(&attrs);
pid_t pid;
extern char **environ;
char *const spawn_argv[] = {"wc" , NULL};
posix_spawnp(&pid, "wc", &fd_actions, &attrs, spawn_argv, environ);
close(slave_fd); // No longer needed in the parent process
const char *data = "hello world\n";
ssize_t len = strlen(data);
if (write(master_fd, data, len) != len) {
perror("write");
}
// Send the terminal's end of file interrupt
cc_t tty_eof = tty_attrs.c_cc[VEOF];
if (write(master_fd, &tty_eof, sizeof tty_eof) != sizeof tty_eof) {
perror("write EOF");
}
// Wait for wc to exit
int status;
waitpid(pid, &status, 0);
char buffer[1024];
ssize_t bytes = read(master_fd, buffer, 1024);
if (bytes > 0) {
fwrite(buffer, 1, bytes, stdout);
}
close(master_fd);
return 0;
}
編譯并運行時,輸出
1 2 12
uj5u.com熱心網友回復:
這段代碼有兩個問題。
首先,您看到"hello world"了,master_fd因為默認情況下終端會回顯。您需要將終端設定為原始模式以抑制它。
其次,wc在它看到 EOF 之前不會輸出任何東西,并且在你關閉 master 之前它不會看到 EOF。不只是master_fd_write介意你,還有的所有副本master_fd,包括master_fd它自己。但是,一旦關閉主控,就無法讀取它。
選擇其他一些程式wc來演示posix_openpt.
編輯:可以通過寫入^D(EOT,ascii 4)在不關閉主機的情況下提高從機的檔案結束條件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/527645.html
標籤:C苹果系统
