简体   繁体   English

在C中管道,dup,close和exec的问题

[英]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代码示例,它执行以下操作:

  1. Parent gets a fd from a file using open(). Parent使用open()从文件中获取fd。
  2. Parent creates a child which execs to another program which reads data from the open() func fd used before and writes the output in a pipe. Parent创建一个子程序,该子程序执行到另一个程序,该程序从之前使用的open()函数fd读取数据并将输出写入管道。 (So parent should wait it to end before continuing). (所以父母应该在继续之前等待它结束)。
  3. Same parent then creates another child which is going to exec and read from that write end of the pipe created before and write the output in the stdo. 然后,同一父节点创建另一个子节点,该子节点将执行并读取之前创建的管道的写入结尾,并在stdo中写入输出。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM