是否可以在同一父代创建的两个子进程之间建立管道(LINUX,POSIX)

ero*_*gol 9 c linux ipc pipe

我有多个孩子由同一个父"分叉",我尝试pipe在所有这些子进程之间构建连接,如链表结构.孩子1发送数据给child2,孩子2发送给孩子3 ....孩子N发送给孩子1.有没有正确的方法呢?

此外,如果我在进程之间创建和通信,我如何强制父进程"等待"所有进程完成其工作wait()waitpid()等待第一个完成进程但我需要等待所有进程.这是另一个问题.

谢谢...

dat*_*olf 19

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

ls | grep foo | sort | uniq
Run Code Online (Sandbox Code Playgroud)

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

该书的主页:http://ladweb.net/

要为N个进程构建重定向链,您需要N-1个管道.对于每个重定向,您使用pipe(int fds[2])系统调用创建管道.之后fork(),但在execv使用之前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(...);
}
Run Code Online (Sandbox Code Playgroud)

请注意,管道的数组索引已被选择,如果它们用于stdio重定向,则它们反映标准输入/输出文件描述符.这种选择并非随意.

当然你可以将管道连接到任何文件描述符(例如,有一些应用程序,希望它们的父项打开,比如fd 3和4,连接到管道),大多数shell也直接支持这个(例如1>&3将重定向) stdout进入fd 3).但是,数组索引pipe(int fds[2])当然是0和1.我只是告诉这个,因为我有一些货物狂热编程的学生,他们盲目地将目标fds也用于管道系统调用阵列.

等待所有孩子完成使用waitpid(-1, NULL, 0)- 我认为这是我的前回答者的意思-1,这意味着:等待所有子进程完成.另一种选择是调用wait()一个循环,它将返回刚刚终止的子进程的pid.如果再次调用并且仍然有一个孩子在运行,它将再次阻止.如果没有孩子,它将返回-1; 我更喜欢waitpid解决方案.


Mar*_*rkR 5

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

让不使用管道的 FD 处于打开状态是一种失败,因为这可能会让其他人永远等待管道的末端。所有写入器必须在读取器收到 EOF 之前关闭。