如何解决2 管道问题,为什么我的父进程一直在等待?
我正在尝试制作一个包含 2 个管道的程序,在我的程序中,子项将首先运行,父项将在最后运行。 结果显示Child 2,然后Child1,并保持pending。 看来我的父母还在等待一些子进程完成,但我在这个程序中只有 2 个子进程~请帮帮我 :) 谢谢!
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/types.h>
int main(void)
{
int pipefd[2];
int pipefd2[2];
int rv= pipe(pipefd);
assert(rv > -1);
int cid = fork();
assert(cid > -1);
int status;
if( cid > 0 ){
//waitpid(cid,NULL,0);
printf("P %d %d\n",getpid(),getppid());
wait(NULL);
printf("Parent \n");
close(0);
dup(pipefd[0]);
close(pipefd[0]);
close(pipefd[1]);
char *const wc_argv[] = {"wc","-l",NULL};
execvp("wc",wc_argv);
//Parent - Redirect stdout to the write end of the pipe,and execute "ls -l"
}else{
int rv1= pipe(pipefd2);
assert(rv1 > -1);
int cid1 = fork();
assert(cid1 > -1);
if(cid1>0){
printf("C1 %d %d\n",getppid());
wait(NULL);
printf("Child1\n");
//Child 1 (parent of child 2)
close(0);
dup(pipefd[0]);
close(1);
dup(pipefd2[1]);
close(pipefd[0]);
close(pipefd[1]);
close(pipefd2[0]);
close(pipefd2[1]);
char *const grep_argv[] = {"grep","D",NULL};
execvp("grep",grep_argv);
}else{
printf("C2 %d %d\n",getppid());
printf("Child2\n");
//Child 2 (child of child 1)
close(1);
dup(pipefd2[1]);
close(pipefd2[0]);
close(pipefd2[1]);
close(pipefd[0]);
close(pipefd[1]);
char *const ls_argv[] = {"ls",NULL};
execvp("ls",ls_argv);
}
}
}
解决方法
您的代码存在多个问题。我在评论中指出了一些小问题,但主要可能对您描述的不当行为负责的是:
-
Child 1 和 parent 都将
pipefd[0]
重定向到它们的标准输入。可能您希望 child 1 将pipefd2[0]
重定向到其标准输入,但您绝对不希望两者具有相同的标准输入。 -
Child 1 将其标准输出重定向到
pipefd2[1]
,一旦您纠正了上一个问题,该管道的另一端将成为其标准输入。您似乎想要重定向到pipefd[1]
,目前根本没有提供该服务。 -
子 1 在继续之前等待子 2。这是不惯用的和有风险的,因为如果孩子 2 填充第二个管道的缓冲区,您将陷入死锁,因此在终止之前阻塞。管道是数据管道。尽管它们确实有内部缓冲区,但这应该被视为一个实现细节。依靠管道进行缓冲是不正确的。正确的模型是数据从管道的读端消费,同时数据被写入管道的写端。
-
父进程在继续之前等待子进程 1。与孩子 1 的等待一样,这是有风险且不符合习惯的。
此外,正如@IanAbott 在评论中所说的那样,按照您安排管道的方式,孩子 1 等待孩子 2 将可靠地产生死锁。后者执行一个程序,该程序将读取其标准输入到最后,但在管道的另一端关闭之前它不会在其输入上看到 EOF,并且永远不会关闭,因为子 1 在它之前等待子 2 完成收益。我认为没有必要等待——无论是孩子 1 还是父母——他们可以而且应该被移除。
,天啊!!谢谢大家 这是我第一次在堆栈溢出中发布问题。 我不敢相信你们这么有帮助,非常感谢 我现在已经解决了我的问题。 我可以相信我犯了一个非常简单的错误,那就是 Child1
close(0);
dup(pipefd2[0]);
close(1);
dup(pipefd[1]);
原来,我的程序会先运行parent,然后我想修改它,然后我只是想交换child 2和parent,一切都会好起来的,但是我忘了修改child1的内容。 无论如何,你们是如此乐于助人,希望你们保持安全并继续我们的冒险:)
,顺便说一句,我可以看到对我的代码有很多建议,我会尝试消化它:)。再次感谢大家!!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。