我正在重定向子进程的输出:
int pipefd[2];
pipe(pipefd);
pid_t pid = fork(); /* Create a child process */
switch (pid) {
case -1: /* Error */
cout << "Uh-Oh! fork() failed.\n";
exit(1);
case 0: /* Child process */
close(pipefd[0]);
dup2(pipefd[1], 1);
dup2(pipefd[1], 2);
close(pipefd[1]);
execv(args[0], (char * const *)args);
cout << "execv() error" << endl;
exit(1);
default: /* Parent process */
close(pipefd[1]);
char buffer[1024];
size_t bytes_read = 0;
bytes_read = read(pipefd[0], buffer, sizeof(buffer));
if(bytes_read == -1) {
cout << "read() error" << endl;
exit(1);
}
close(pipefd[0]);
if(bytes_read > 0) {
buffer[bytes_read-1] = '\0'; // Overwrite the newline
}
int status, exit_pid;
while(true) {
exit_pid = waitpid(pid, &status, 0);
if(exit_pid == -1) {
cout << "waitpid() error: " << strerror(errno) << endl;
exit(1);
}
else {
return WEXITSTATUS(status);
}
}
}
当我将它作为一段孤立的代码运行时,这很好用。但是当我将它集成到我的多线程环境中时,会发生一件可怕的事情:read()调用以某种方式读取父进程的其他线程的输出,就好像它是子进程管道的输出一样。 有没有遇到过这样的事情? 我是OS X.
答案 0 :(得分:0)
好吧,我有一个解决方案,即使我不完全理解为什么会这样。
但首先,应该清楚这种行为既不正常也不可预期。使用fork()创建的子进程不会从其父级继承任何正在运行的线程(因此意外输出必须来自父线程)。它有自己的描述符表。因此,当子进程调用dup2()来改变其输出描述符时,这不应该对父进程中的线程产生任何影响。
仅在execv()调用失败的情况下才会出现此问题。在这些情况下,我期望终止子进程以关闭其所有文件描述符。但这没有发生,或者至少它与明确调用close()没有相同的效果。因此,在execv()之后添加显式的close()调用可以解决问题:
execv(args[0], (char * const *)args);
close(1);
close(2);
exit(1);
管道的写端描述符的关闭将导致读端上的读操作接收0,因此知道不再读取。 但是,我仍然不知道以下内容:
如果有人能够阐明这一点,我们将不胜感激。