一根管道的哪一端是输入端,哪一端是输出端?

7

最近我开始怀疑自己错误地使用了管道的末尾:

从man手册中可以看到:

pipe() 创建一个管道.. ..pipefd[0] 指向管道的读取端。pipefd[1] 指向管道的写入端。

所以在我的脑海中,它应该是这样的:

                .---------------------------.
               /                            /\
              | pipedfd[0]       pipedfd[1]|  |
process1 ---> |                            | -----> process2
              | input                output|  |
               \____________________________\/

然而,我这里的代码可以正常工作,表明情况并非如此:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
  int pipedfd[2];
  char buf[30];

  pipe(pipedfd);
  printf("writing to file descriptor #%d\n", pipedfd[1]);
  write(pipedfd[1], "test", 5);
  printf("reading from file descriptor #%d\n", pipedfd[0]);
  read(pipedfd[0], buf, 5);
  printf("read \"%s\"\n", buf);

  return 0;
}

即它写入管道的输出并从管道的输入中读取?

尝试检查读取和写入的错误返回,一切都会变得清晰明了。 - bmargulies
2
读取管道的末端 = 从哪里读取 = pipefd[0](不是您图表中写入的部分)。听起来非常简单。 - Jon
@Jon 当我想到物理管道时,我认为它有一个角落用于输入(获取水)和一个角落用于输出(放水)。我不认为水会流向管道的输出端(写入)。在我的想象中,这是违反直觉的。不,我不是一名管工。 - Pithikos
@Pithikos:在这种情况下,物理管道的比喻确实更多地带来了负面影响。 :) - Jon
@Jon:实际上,物理隐喻正是它的工作原理:你把东西塞进一个端口(fd[1]),然后从另一个端口取出来(fd[0])。如果你试图放入太多的东西,它会阻塞直到有东西被取出来。 - DarkDust
显示剩余2条评论
2个回答

6
简而言之,交换您的图表中数字01,就可以得到我下面要描述的内容。
来自Mac OS X man页面: pipe()函数创建管道(允许单向数据流的对象)并分配一对文件描述符。第一个描述符连接到管道的读端;第二个连接到写端。
写入fildes [1]的数据出现在(即可从)fildes [0]中读取。这使得一个程序的输出可以发送到另一个程序:源的标准输出设置为管道的写端;接收器的标准输入设置为管道的读端。管道本身持续存在,直到关闭其所有关联的描述符。
我将描述它通常如何使用,这可能会澄清它。想象一下,您有一个进程,并想要生成一个子进程,向其中发送命令。
首先,调用pipe并获取两个文件描述符。
然后调用fork创建子进程。 - 在子进程中,关闭写入文件描述符(fd[1]),并保留读取的文件描述符开放; - 在父进程中,关闭读取文件描述符(fd[0]),并保留写入的文件描述符开放。
现在,父进程可以写入他的管道(fd[1]),而子进程可以在另一个管道上读取(fd[0])。
关闭不是必需的,但通常会执行。如果需要双向通信,您需要第二组文件描述符以及对pipe的第二次调用,或者使用像Unix域套接字或命名管道这样的双向通道。

2

Linux man page for pipe解释如下:

向管道写入的数据由内核缓冲,直到从管道的读端读取。

也就是说,您需要从fd[0]读取,向fd[1]写入。


2
@JonPurdy:是的,那就是他的代码在做的事情,他的图表(和理解)是相反的。 - Hasturkun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接