好。我有点理解管道如何工作以及为什么在任何子进程中exec之前都使用了dup / dup2。
但我需要'close(int fd)'的帮助。 为了说清楚,我想问你任何伪代码或任何C代码示例执行以下操作:
只用一根烟斗才能做到这一点吗?
对我来说,棘手的问题不是创建管道并使用dup2和东西重定向通道,它知道何时何地关闭()所有fd通道。
如果你能解释我如何做这样的事情以及何时何地以一个例子来关闭频道我想我绝对会理解这一切。
非常感谢你们。
答案 0 :(得分:0)
下面是一个完整的示例。 WhozCraig已经告诉我们,父级无需等待子级1结束就可以继续,因为子级2必须读取管道直到EOF。 (相反,父级一定不要等待,因为管道缓冲区可能不够大,无法容纳所有文件数据。)当然,只需要一个管道,其中子项1写入一端子2从另一个读取。因此,不需要dup
。
父母必须在何时何地关闭管道?
如果需要管端的孩子将其打开,则父母可以在不再需要它们时立即关闭管端。 e。在我们的示例中,父级可以在派生子级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
}