gpt4 book ai didi

c++ - fork 进程后的 Exec 在程序完成之前不返回结果

转载 作者:太空宇宙 更新时间:2023-11-04 01:27:42 24 4
gpt4 key购买 nike

我正在尝试创建一个程序,它 fork 一次,当父进程等待子进程终止时,这个子进程再次 fork,然后执行两个 exec。程序上有一个 Pipe,我已经检查了程序上每个 dup2() 和 pipe() 的返回值——只是在这里省略它们以使其看起来更简洁——。问题是我只得到 ls -a | 的结果sort -r 在程序完成后。代码是:

#include <cstdio>
#include <cstring>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char *argv[]) {
printf("Shell> \n"); fflush(stdout);

pid_t pid1;
pid_t pid2;
int status = 0;
int fd[2];

if(pipe(fd) < 0) {
printf("FATAL ERROR.\n");
}

pid1 = fork();

if(pid1 > 0) { // Parent
waitpid(pid1, &status, 0);
printf("\t\t------PID1 Complete-------\n\n");
}
else { // Child
if(pid1 == 0) {
printf("ON CHILD\n");

pid2 = fork();

if(pid2 > 0) { // Child -> Parent
printf("ON CHILD-Parent\n");
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
waitpid(pid2, &status, 0);
printf("ON CHILD-Parent after wait\n");
execlp("sort", "sort", "-r", NULL);
perror("Problem with execlp\n");
exit(1);
}
else { // Child -> Child
printf("ON CHILD->Child\n");
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
execlp("ls", "ls", "-a", NULL);
perror("Problem with execvp\n");
exit(1);
}
} // End of if(pid1 == 0)
} // End of Child

printf("\nEnd of program.\n");

return 0;
}

我当前的输出是:

Shell> 
ON CHILD
ON CHILD-Parent
ON CHILD->Child
ON CHILD-Parent after wait

我认为问题出在等待中,但我就是想不出如何解决这个问题。有任何想法吗?谢谢!

最佳答案

问题是您在祖父进程中调用了pipe。在孙进程 (ls -a) 退出后,父进程 (sort -r) 会无限期地阻塞等待从管道读取更多输入,因为某些进程 - 祖 parent - 持有管道写入端的打开描述符。

如果您关闭祖父进程中的管道描述符,或者更好的是将 pipe 调用移动到第一个 fork 进程中,那么排序过程将在最后一个具有打开描述符的进程时终止写管道导出的末端(DEMO):

int main() {
// Turn off buffering of stdout, to help with debugging
setvbuf(stdout, NULL, _IONBF, 0);
printf("Shell> \n");

pid_t pid1 = fork();
if(pid1 < 0) {
perror("fork failed");
}

if(pid1 > 0) { // Parent
int status;
waitpid(pid1, &status, 0);
printf("\t\t------PID1 Complete (%d) -------\n\n", status);
} else { // Child
printf("ON CHILD\n");

int fd[2];
if(pipe(fd) < 0) {
perror("pipe failed");
return 1;
}

pid_t pid2 = fork();
if(pid2 < 0) {
perror("fork failed");
}

if(pid2 > 0) { // Child -> Parent
printf("ON CHILD-Parent\n");
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("sort", "sort", "-r", NULL);
perror("Problem with execlp");
return 1;
} else { // Child -> Child
printf("ON CHILD->Child\n");
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
execlp("ls", "ls", "-a", NULL);
perror("Problem with execvp");
return 1;
}
}

printf("\nEnd of program.\n");
}

程序的另一个问题是 @nategoose评论:如果“ls -a”的输出太大而无法放入管道缓冲区,则调用 waitpid 可能会导致死锁。没有理由等待,所以应该简单地消除它。

关于c++ - fork 进程后的 Exec 在程序完成之前不返回结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28352868/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com