管道作为进程间通信

时间:2008-12-12 16:18:02

标签: unix piping

我有兴趣编写独立的程序模块,这些程序模块作为独立的线程运行,我可以用管道挂钩。我的动机是我可以完全独立地编写和测试每个模块,甚至可以用不同的语言编写它们,或者在不同的机器上运行不同的模块。这里有各种各样的可能性。我已经使用了一段时间的管道,但我不熟悉它的行为的细微差别。

  • 看起来接收端会阻止等待输入,这是我期望的,但是发送端阻塞有时会等待某人从流中读取吗?
  • 如果我在流中写了一个eof,我可以继续写入该流,直到我关闭它吗?
  • 命名和未命名管道的行为是否存在差异?
  • 我先用命名管道打开管道的哪一端有用吗?
  • 不同Linux系统之间管道的行为是否一致?
  • 管道的行为是否取决于我正在使用的shell或我配置它的方式?
  • 如果我想以这种方式使用烟斗,我还应该问其他问题或者我应该注意的问题吗?

3 个答案:

答案 0 :(得分:4)

哇,这是很多问题。让我们看看我能否涵盖所有内容......

  

似乎接收端会   阻止等待输入,我会   预期

您希望正确的“读取”调用将会阻塞,直到出现某些内容。但是,我相信有一些C函数可以让你“窥视”在管道中等待的数量(以及多少)。不幸的是,我不记得这是否会阻止。

  

发送端有时会阻塞   等待某人从中读   流

不,发送不应该阻止。如果这是跨越网络到另一台计算机的管道,请考虑这些后果。您是否希望等待(通过可能的高延迟)让另一台计算机响应它收到它?现在,如果目的地的阅读器句柄已关闭,则这是一种不同的情况。在这种情况下,您应该进行一些错误检查以处理它。

  

如果我在流中写了一个eof,我可以   继续写入该流   直到我关闭它

我认为这取决于您使用的语言及其管道的实现。在C中,我会说不。在linux shell中,我会说是的。其他有更多经验的人则必须回答这个问题。

  

行为有差异吗?   命名和未命名的管道?   据我所知,是的。但是,我对named vs unnamed没有多少经验。我相信不同之处是:

  • 单向与双向通信
  • 读取和写入线程的“in”和“out”流
  

管道I的哪一端是否重要   首先打开命名管道?

通常不会,但是在尝试创建和链接线程的初始化时可能会遇到问题。您需要有一个主线程来创建所有子线程并相互同步它们各自的管道。

  

管道的行为是否一致   不同的Linux系统之间?

同样,这取决于使用什么语言,但通常是肯定的。有没有听说过POSIX?这是标准(至少对于Linux,Windows自己做的事情)。

  

管道的行为是否依赖   我正在使用的外壳或我的方式   配置了吗?

这是一个灰色地带。答案应该不是因为shell本质上应该进行系统调用。但是,到那时为止的所有事情都可以争夺。

  

我还有其他问题吗?   请问

您提出的问题表明您对系统有一个很好的理解。继续研究并专注于你将要处理的水平(shell,C等)。通过尝试,你会学到很多东西。

答案 1 :(得分:4)

这完全基于类UNIX系统;我不熟悉最新版Windows的具体行为。

看起来接收端会阻止等待输入,这是我期望的,但是发送端阻塞有时会等待某人从流中读取吗?

是的,虽然在现代机器上它可能不会经常发生。管道有一个可能可能填满的中间缓冲区。如果是这样,管道的写入侧确实会阻塞。但是如果你考虑一下,就没有很多文件可以冒这个风险。

如果我在流中写了一个eof,我可以继续写入该流,直到我关闭它吗?

嗯,你的意思是像CTRL-D,0x04?当然,只要流设置那样。即

506 # cat | od -c
abc
^D
efg
0000000    a   b   c  \n 004  \n   e   f   g  \n                        
0000012

命名和未命名管道的行为是否存在差异?

是的,但它们是微妙的,并且依赖于实现。最大的一个是你可以在另一端运行之前写入命名管道;使用未命名的管道,文件描述符在fork / exec进程期间共享,因此在没有进程的情况下无法访问临时缓冲区。

使用命名管道首先打开管道的哪一端?

不。

管道的行为是否在不同的Linux系统之间保持一致?

在合理范围内,是的。缓冲区大小等可能会有所不同。

管道的行为是否依赖于我正在使用的shell或我配置它的方式?

没有。当你创建一个管道时,在你的父进程(shell)创建一个具有一对文件描述符的管道,然后做一个像这个伪代码的fork exec:

<强>父

create pipe, returning two file descriptors, call them fd[0] and fd[1]
fork write-side process
fork read-side process

<强>写侧

close fd[0]
connect fd[1] to stdout
exec writer program

<强>阅读侧

close fd[1]
connect fd[0] to stdin
exec reader program

如果我想以这种方式使用烟斗,我应该问的其他问题或者我应该注意的问题吗?

你想要做的一切真的要像这样排成一行吗?如果没有,您可能想要考虑更通用的架构。但是,通过管道的“窄”界面进行交互的大量独立过程的观点是可取的。

[更新:我首先反转了文件描述符索引。他们现在是正确的,请参阅man 2 pipe。]

答案 2 :(得分:4)