[英]Trouble with pipes, dup, close and exec in C
Well. 好。 I kinda understand how pipes work and why is dup/dup2 used before an exec in any child process.
我有点理解管道如何工作以及为什么在任何子进程中exec之前使用dup / dup2。
But I need help with the 'close(int fd)' thing. 但我需要'close(int fd)'的帮助。 To make it clear I would like to ask you for any pseudocode or any C code example which does the following:
为了说清楚,我想问你任何伪代码或任何C代码示例,它执行以下操作:
Is it even posible to do this with only one pipe? 只用一根烟斗就可以做到这一点吗?
The tricky thing here for me is not creating the pipe and redirecting channels with dup2 and stuff, it is knowing where and when to close() all the fd channels. 对我来说,棘手的事情不是创建管道并使用dup2和东西重定向通道,它知道何时何地关闭()所有fd通道。
If you could explain me how to do a thing like that and when and where to close the channels with an example I think I would definetly understand it all. 如果你能解释我如何做这样的事情,以及何时何地以一个例子来关闭频道,我想我绝对会理解这一切。
Thanks a lot guys. 非常感谢你们。
Below is a complete example. 以下是一个完整的例子。 WhozCraig already told that there's no need for parent to wait for child 1 to end before continuing, since child 2 has to read the pipe until EOF.
WhozCraig已经告诉父母在继续之前不需要等待孩子1结束,因为孩子2必须在EOF之前读取管道。 (On the contrary, the parent must not wait, because the pipe buffer might not be large enough to hold all the file data.) Of course there's only one pipe needed, where child 1 writes to one end and child 2 reads from the other.
(相反,父级必须不等待,因为管道缓冲区可能不足以容纳所有文件数据。)当然只需要一个管道 ,其中子级1写入一端而子级2读取另一端。 And for that no
dup
is needed. 因此,不需要
dup
。
When and where does the parent have to close the pipe channels?
父母何时何地必须关闭管道渠道?
The parent may close the pipe ends as soon as it doesn't need them any longer, provided that a child which needs a pipe end has it open, ie in our case, the parent may close (its descriptor of) the write end after child 1 has been forked, and the parent may close the read end after child 2 has been forked, since the children inherit the pipe descriptors, and they remain usable until the children close them at exit. 只要需要管道末端的子项打开它,父级可以在不再需要它们时立即关闭管道末端,即在我们的情况下,父级可以关闭(其描述符)写入结束之后子级1已经被分叉,并且父级可以在子级2被分叉之后关闭读取端,因为子级继承了管道描述符,并且它们保持可用直到子级在退出时关闭它们。
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
main(int argc, char *argv[])
{
if (argc <= 1) return 1;
int fd = open(argv[1], O_RDONLY); // Parent gets a fd from a file.
if (fd < 0) return perror(argv[1]), 1;
int pipefd[2];
if (pipe(pipefd) < 0) return perror("pipe"), 1;
char in[8], out[8];
sprintf(in, "FD:%d", fd); // reads data from the open() func fd
sprintf(out, "FD:%d", pipefd[1]); // writes the output in a pipe
switch (fork())
{ // Parent creates a child which execs to another program, e. g. "socat"
case -1: return perror("fork 1"), 1;
case 0: execlp("socat", "socat", "-u", in, out, NULL);
return perror("execlp 1"), 1;
}
close(pipefd[1]); // parent may close write end, since child has it open
sprintf(in, "FD:%d", pipefd[0]); // read from the pipe created before
sprintf(out, "FD:%d", 1); // write the output in the stdo
switch (fork())
{ // Same parent then creates another child which is going to exec
case -1: return perror("fork 2"), 1;
case 0: execlp("socat", "socat", "-u", in, out, NULL);
return perror("execlp 2"), 1;
}
close(pipefd[0]); // parent may close read end, since child has it open
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.