是否可以在由同一个父进程(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
Is it possible to have pipe between two child processes created by same parent (LINUX, POSIX)
提问by erogol
I have multiple child "forked" by the same parent and I try to construct pipe
connection 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 execv
ing 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之后,但在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(...);
}
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 waitpid
solution.
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 之前,所有作者都必须关闭。