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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5225810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:09:41  来源:igfitidea点击:

Is it possible to have pipe between two child processes created by same parent (LINUX, POSIX)

clinuxipcpipe

提问by erogol

I have multiple child "forked" by the same parent and I try to construct pipeconnection between all these child processes like a linked list structure. Child 1 sends data to child2, child 2 to child 3.... child N to child 1. Is there any proper way to do it?

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

In addition, if I create and communicate between processes how I force the parent to "wait" all the process to finish their job since wait()or waitpid()waits for first finished process but I need to wait them all. It is the another question that arises.

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

Thanks...

谢谢...

采纳答案by datenwolf

This is essentially what a shell does if build a redirection chain, i.e. something like

如果构建重定向链,这基本上就是 shell 所做的事情,即类似

ls | grep foo | sort | uniq

There are some excellent introducionary texts on Unix programming, in which a simple shell is implemented through the book. And one of the tasks of a shell is redirection. One of these books is "Linux Application Programming" by Michael K. Johnson and Erik W. Troan.

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

The book's homepage: http://ladweb.net/

本书主页:http: //ladweb.net/

To build a chain of redirections for N processes you need N-1 pipes. For each redirection you create a pipe using the pipe(int fds[2])system call. After fork()ing, but before execving use dup2(int from, int to)to "connect" a pipe's end to the standard input (0) or standard output of each process. Here's a overly simplified code, without error checking:

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

Take note that the pipe's array indices have been choosen in a way that they reflect the standard input/output file descriptors if they're used for stdio redirection. This choice was not arbitrary.

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

Of course you can connect pipes to any file descriptors (e.g. there are some applications, which expect their parent to open, say fd 3 and 4, connected to pipes) and most shells directly support this, too (for example 1>&3 will redirect stdout into fd 3). However the array indices for pipe(int fds[2])are 0 and 1 of course. I'm just telling this, because I had some cargo-cult-programming students, which mindlessly took the target fds also for the pipe syscall array.

当然,您可以将管道连接到任何文件描述符(例如,有些应用程序希望它们的父级打开,例如 fd 3 和 4,连接到管道)并且大多数 shell 也直接支持这一点(例如 1>&3 将重定向标准输出到 fd 3)。然而,数组索引pipe(int fds[2])当然是 0 和 1。我只是告诉这个,因为我有一些货物崇拜编程的学生,他们盲目地将目标 fds 也用于管道系统调用数组。

To wait for all the children to finish use waitpid(-1, NULL, 0)– I think that's the -1 my pre-answerer meant, which means: Wait for all child processes to finish. The other option was calling wait()in a loop which will return the pid of the just terminated child. If called again and there's still a child running, it will block again. If there's no child left, it will return -1; I prefer the waitpidsolution.

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

回答by Ignacio Vazquez-Abrams

Create all the pipes first, then spawn all the children with the appropriate pipe ends in FDs 0 and 1.

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

As for waiting, just keep waiting until it returns -1.

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

回答by MarkR

Yes, this is fairly easy, you just need to create all the pipes in the parent, and remember to close the pipes / ends of pipes in the child(ren) that you don't need them in.

是的,这很容易,您只需要在父级中创建所有管道,并记住关闭您不需要它们的子级(ren)中的管道/管道末端。

Leaving FDs of the pipes open in children which aren't using them is a FAIL as it can make others wait forever for the end of the pipe. All writers must close before the reader gets an EOF.

让不使用管道的儿童打开管道的 FD 是失败的,因为它可以让其他人永远等待管道的尽头。在读者获得 EOF 之前,所有作者都必须关闭。