Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是否可以在同一父进程(LINUX、POSIX)创建的两个子进程之间使用管道_C_Linux_Ipc_Pipe - Fatal编程技术网

C 是否可以在同一父进程(LINUX、POSIX)创建的两个子进程之间使用管道

C 是否可以在同一父进程(LINUX、POSIX)创建的两个子进程之间使用管道,c,linux,ipc,pipe,C,Linux,Ipc,Pipe,我有多个子进程被同一个父进程“分叉”,我尝试在所有这些子进程之间构建pipe连接,就像链表结构一样。子1将数据发送给子2,子2将数据发送给子3。。。。孩子N对孩子1。有什么合适的方法吗 此外,如果我在进程之间创建和通信,我将如何强制父进程“等待”所有进程以完成其作业,因为wait()或waitpid()等待第一个完成的进程,但我需要等待所有进程。这是另一个问题 谢谢…首先创建所有管道,然后在FDs 0和1中生成具有适当管道端点的所有子管道 至于等待,只需一直等待,直到它返回-1。这基本上就是sh

我有多个子进程被同一个父进程“分叉”,我尝试在所有这些子进程之间构建
pipe
连接,就像链表结构一样。子1将数据发送给子2,子2将数据发送给子3。。。。孩子N对孩子1。有什么合适的方法吗

此外,如果我在进程之间创建和通信,我将如何强制父进程“等待”所有进程以完成其作业,因为
wait()
waitpid()
等待第一个完成的进程,但我需要等待所有进程。这是另一个问题


谢谢…

首先创建所有管道,然后在FDs 0和1中生成具有适当管道端点的所有子管道


至于等待,只需一直等待,直到它返回-1。

这基本上就是shell在构建重定向链时所做的,例如

ls | grep foo | sort | uniq
有一些关于Unix编程的优秀介绍性文本,其中通过本书实现了一个简单的shell。shell的任务之一是重定向。其中一本书是Michael K.Johnson和Erik W.Troan的《Linux应用程序编程》

该书的主页:

要为N个进程构建重定向链,您需要N-1个管道。对于每个重定向,使用
管道(int fds[2])
系统调用创建一个管道。在
fork()
ing之后,但在
execv
ing之前,使用
dup2(int-from,int-to)
将管道末端“连接”到每个进程的标准输入(0)或标准输出。这是一个过于简化的代码,没有错误检查:

int pipe_A[2];
int pipe_B[2];

pipe(pipe_A);
pipe(pipe_B);

pid_t pid_A, pid_B, pid_C;

if( !(pid_A = fork()) ) {
    dup2(pipe_A[1], 1); /* redirect standard output to pipe_A write end */
    execv(...);
}

if( !(pid_B = fork()) ) {
    dup2(pipe_A[0], 0); /* redirect standard input to pipe_A read end */
    dup2(pipe_B[1], 1); /* redirect standard output to pipe_B write end */
    execv(...);
}

if( !(pid_C = fork()) ) {
    dup2(pipe_B[0], 0); /* redirect standard input to pipe_B read end */
    execv(...);
}
请注意,选择管道的数组索引时,如果将其用于stdio重定向,它们将反映标准的输入/输出文件描述符。这一选择并非武断

当然,您可以将管道连接到任何文件描述符(例如,有些应用程序希望其父级打开,例如fd 3和fd 4连接到管道),大多数Shell也直接支持这一点(例如1>&3将标准输出重定向到fd 3)。但是
管道(int fds[2])
的数组索引当然是0和1。我这么说是因为我有一些cargo cult编程专业的学生,他们毫无意识地将目标fds也用于管道系统调用数组


要等待所有子进程完成,请使用
waitpid(-1,NULL,0)
——我想这就是我的预回答者的-1意思,意思是:等待所有子进程完成。另一个选项是在循环中调用
wait()
,该循环将返回刚刚终止的子项的pid。如果再次调用,但仍有一个子项在运行,它将再次阻塞。如果没有剩余的孩子,它将返回-1;我更喜欢
waitpid
解决方案。

是的,这相当简单,您只需要在父级中创建所有管道,并记住关闭子级(ren)中不需要的管道/管道末端


让未使用管道的儿童打开管道的FD是一个失败,因为这会让其他人永远等待管道的结束。在读者收到EOF之前,所有的编剧都必须关闭。

我不明白“一直等到它返回-1”是什么意思?你的意思是“等待(-1);”还是什么?继续在循环中调用它,直到它返回-1。快速提问,当我使用上述代码时,我的程序挂起在第二个execv上,我想因为它正在等待stdin的EOF。我该如何关闭stdin?@TrewTzu:在stdin被dup2(pipe_A[0],0)替换后,你不能关闭它,因为它会关闭管道。我也不明白为什么execv应该阻止。但是execv不会返回,它将用调用的程序替换进程。这就是为什么这个过程是事先分岔的。您正在哪个操作系统上尝试此操作?这有点晚了,但是看看这段代码,后面的if语句不应该改为“elseif”吗?否则,第一个fork的子级和父级都将运行第二个。@JacobSharf:No,因为
exec…
将替换进程映像。if语句中
exec…
之后的所有内容都不会执行。