管道输出到 C 中的 fork
Piping output to forks in C
我在 progs 中有多个进程,我希望将输出从一个进程按顺序传输到另一个进程。我相信我已经将一个进程的标准输入链接到前一个进程的读取端,并将标准输出链接到管道的写入端。我仍然没有看到输出。我是否遗漏了此处的链接?
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]);
}
您的代码包含一个杂散的 close(pipeFds[i]);
您必须关闭 // parent process stuff
内的管道。使用您的代码,每个 child 保持前一个 children 的 pipeFds
打开。例如
} else {
// parent process stuff
if (i > 0)
close(pipeFds[i - 1][READ_END]);
close(pipeFds[i - 1][READ_END]);
}
一对 fds[2]
可能比 numProg
对更有效。
记住你需要关闭所有个管道,在每个进程中,它才能工作。
示例:
如果numProg=2
您创建了 2 个管道和 2 个子进程。添加父进程,有 3 个进程 运行,在 每个 中,您最终需要关闭 所有 管道。
对于 child_pid==0
,您关闭 [READ_END]
但永远不会关闭 [WRITE_END]
。
对于 child_pid==1
你做一个 close(pipeFds[1])
。您需要指定 [READ_END]
和 [WRITE_END]
.
然后每个子进程通过 execvp
退出,但是,如果它失败,则可能 return 控制。来自 man 页面:
exec() 系列函数用新的过程映像替换当前过程映像。 .. 如果发生错误,exec() 函数仅 return。
因此您可能希望在 execvp
之后添加一个 _exit(0);
以确保即使 execvp
失败,每个子进程也能正常退出。
父进程关闭除最后一个以外的所有管道。所以在 NumProg=2
的例子中,pipeFd[1]
的 [READ_END]
和 [WRITE_END]
都永远不会关闭。
最后,父进程应该 wait
关闭所有子进程(使用 while(wait(NULL) != -1);
),否则你可能会得到僵尸或孤儿进程。
我在 progs 中有多个进程,我希望将输出从一个进程按顺序传输到另一个进程。我相信我已经将一个进程的标准输入链接到前一个进程的读取端,并将标准输出链接到管道的写入端。我仍然没有看到输出。我是否遗漏了此处的链接?
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]);
}
您的代码包含一个杂散的
close(pipeFds[i]);
您必须关闭
// parent process stuff
内的管道。使用您的代码,每个 child 保持前一个 children 的pipeFds
打开。例如} else { // parent process stuff if (i > 0) close(pipeFds[i - 1][READ_END]); close(pipeFds[i - 1][READ_END]); }
一对
fds[2]
可能比numProg
对更有效。
记住你需要关闭所有个管道,在每个进程中,它才能工作。
示例:
如果numProg=2
您创建了 2 个管道和 2 个子进程。添加父进程,有 3 个进程 运行,在 每个 中,您最终需要关闭 所有 管道。
对于 child_pid==0
,您关闭 [READ_END]
但永远不会关闭 [WRITE_END]
。
对于 child_pid==1
你做一个 close(pipeFds[1])
。您需要指定 [READ_END]
和 [WRITE_END]
.
然后每个子进程通过 execvp
退出,但是,如果它失败,则可能 return 控制。来自 man 页面:
exec() 系列函数用新的过程映像替换当前过程映像。 .. 如果发生错误,exec() 函数仅 return。
因此您可能希望在 execvp
之后添加一个 _exit(0);
以确保即使 execvp
失败,每个子进程也能正常退出。
父进程关闭除最后一个以外的所有管道。所以在 NumProg=2
的例子中,pipeFd[1]
的 [READ_END]
和 [WRITE_END]
都永远不会关闭。
最后,父进程应该 wait
关闭所有子进程(使用 while(wait(NULL) != -1);
),否则你可能会得到僵尸或孤儿进程。