一尘不染

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

linux

我有多个由同一父节点“分叉”的子节点,并且我尝试pipe在所有这些子进程之间构建连接,例如链表结构。孩子1向孩子2发送数据,孩子2向孩子3发送数据。孩子N向孩子1发送数据。有什么适当的方法吗?

另外,如果我在流程之间创建和通信,如何迫使父级“等待”所有流程以完成其工作,wait()或者waitpid()等待第一个完成的流程,但我需要等待所有流程。这是另一个出现的问题。

谢谢…


阅读 420

收藏
2020-06-02

共1个答案

一尘不染

本质上,这就是外壳程序构建重定向链的方式,即类似

ls | grep foo | sort | uniq

在Unix编程上有一些很棒的介绍性文本,其中通过本书实现了一个简单的shell。Shell的任务之一是重定向。其中一本书是Michael K.
Johnson和Erik W. Troan撰写的“ Linux Application Programming”。

本书的主页: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(...);
}

请注意,如果将管道的数组索引用于stdio重定向,则选择它们的方式应反映标准的输入/输出文件描述符。这个选择不是任意的。

当然,您可以将管道连接到任何文件描述符(例如,有些应用程序期望它们的父级打开,例如连接到管道的fd
3和4),并且大多数shell也直接支持此操作(例如1>&3将重定向)进入fd 3)。但是,数组的索引pipe(int fds[2])当然是0和1。我之所以这样说,是因为我有一些对货物狂热编程的学生,他们盲目地将目标fds也用于管道syscall数组。

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

2020-06-02