问题描述
我在编中有多个进程,我希望按顺序将输出从一个进程传递到另一个进程。我相信我已经将一个进程的stdin链接到前一个进程的读取端,并将stdout链接到管道的写端。我仍然没有看到输出。我在这里的链接中缺少什么吗?
int pipeFds[numProg][2];
for (int i = 0; i < numProg; i++) {
if (pipe(pipeFds[i]) != 0) { // create pipe for each process
printf("Failed to create pipe!");
exit(1);
}
child_pid = fork();
if (child_pid == -1) {
printf("Error while creating fork!");
exit(1);
}
if (child_pid == 0) {
if (i == 0) {
close(pipeFds[i][READ_END]); // close STDIN first process since it does not read
} else {
// change stdin to read end of pipe for intermediary processes
close(pipeFds[i]);
dup2(pipeFds[i - 1][READ_END],STDIN_FILENO);
}
dup2(pipeFds[i][WRITE_END],STDOUT_FILENO); // change stdout to write end of pipe
execvp(progs[i][0],(char *const * )progs[i]);
} else {
// parent process stuff
}
}
// Close pipes except last pipe for EOF
for (int i = 0; i < numProg - 1; i++) {
close(pipeFds[i][READ_END]);
close(pipeFds[i][WRITE_END]);
}
解决方法
-
您的代码包含一个流浪
get
-
您必须关闭
close(pipeFds[i]);
中的管道。使用您的代码,每个孩子都会使先前孩子中的// parent process stuff
保持打开状态。例如pipeFds
-
使用一对
} else { // parent process stuff if (i > 0) close(pipeFds[i - 1][READ_END]); close(pipeFds[i - 1][READ_END]); }
而不是fds[2]
对可能更有效。
请记住,您需要在每个流程中关闭所有管道,以使其正常工作。
示例:
如果numProg=2
创建2个管道和2个子进程。添加父级后,将运行3个进程,并且在每个进程中,您最终需要关闭所有管道。
对于child_pid==0
,您需要关闭[READ_END]
,但不要关闭[WRITE_END]
。
对于child_pid==1
,您执行close(pipeFds[1])
。您需要指定[READ_END]
和[WRITE_END]
。
然后,每个子进程都通过execvp
退出,但是如果失败,它可能会返回控制权。在man页面上:
exec()系列函数将当前过程映像替换为新的过程映像。 .. exec()函数仅在发生错误时返回。
因此,您可能希望在_exit(0);
之后添加execvp
,以确保即使execvp
失败,每个子进程也会正确退出。
父进程将关闭除最后一个管道之外的所有管道。因此,在NumProg=2
的示例中,[READ_END]
的{{1}}和[WRITE_END]
都不会关闭。
最后,父流程应该pipeFd[1]
以便所有子流程关闭(使用wait
),否则您可能最终会遇到僵尸或孤立的流程。