使用命名管道比使用未命名管道有什么优势?

Ank*_*kit 57 pipe

我正在审查 unix 管理员提出的一组面试问题;我找到了一个名为“命名管道”的主题。

我用谷歌搜索了这个话题;在某种程度上我已经能够理解它:-命名管道 || 先进先出

但我仍然觉得我缺乏什么时候使用这种特殊类型的管道的知识。是否存在未命名管道无法工作的特殊情况?

mr.*_*tic 44

命名管道(fifo)有四个三个我能想到的优点:

  • 您不必同时开始读/写过程
  • 您可以拥有多个不需要共同祖先的读者/作者
  • 作为文件,您可以控制所有权和权限
  • 它们是双向的,未命名的管道可能是单向的 *

    *)认为标准壳的|管道是单向的,几发炮弹(kshzsh,和bash)也提供协进程,允许双向通信。POSIX 将管道视为半双工(即每一侧只能读取或写入),pipe()系统调用返回两个文件句柄,您可能需要将一个视为只读,另一个视为只写。一些 (BSD) 系统支持同时读取和写入(POSIX 不禁止),而在其他系统上,您需要两个管道,每个方向一个。检查您的pipe()popen()可能还有popen2()手册页。无方向性可能不依赖于管道是否命名,尽管在 Linux 2.6 上它是依赖的。

(更新,感谢Stephane Chazelas 的反馈)

因此,使用未命名管道无法实现的一项显而易见的任务是传统的客户端/服务器应用程序。

上面关于单向管道的最后一点(受打击的)与 Linux 相关,POSIX(参见 参考资料popen())说管道只需要可读可写,在Linux 上它们是单向的。有关Linux 特定的详细信息 (p787),请参阅了解 Linux 内核(第 3 版。O'Reilly)。其他操作系统提供双向(未命名)管道。

例如,Nagios 使用 fifo 作为其命令文件。各种外部进程(CGI 脚本、外部检查、NRPE 等)向该 fifo 写入命令/更新,这些由持久的 Nagios 进程处理。

命名管道具有与 TCP 连接不同的特性,但存在重要差异。因为一个 fifo 有一个持久的文件系统名称,即使没有读取器,你也可以写入它,不可否认,写入会阻塞(没有异步或非阻塞 I/O),但如果接收器不是,你不会丢失数据开始(或正在重新启动)。

作为参考,另请参阅Unix domain sockets,以及总结了主要IPC方法的这个 Stackoverflow 问题的答案,以及这个关于popen()

  • _你也可以有多个带有未命名管道的读者/作者_。在 Linux 上,它们并不比未命名的管道更具双向性。有一个写端和一个读端,数据只向一个方向流动。当你在写模式下打开一个 fifo 时,你得到了写端,在读模式下是读端,在 rw 模式下,你写到写端并从读取中读取。这与双向管道或 unix 域套接字不同,在双向管道或 unix 域套接字中,每个方向实际上都有两个独立的数据流。 (4认同)

Jon*_*ham 16

未命名或匿名管道提供了一种在不同进程之间进行一对一、单向进程间通信的方法,这些进程通过父子关系或作为提供管道的公共父进程(例如 shell)的子进程相关联过程。因为进程是相关的,文件描述符与管道的关联可以是隐式的,并且不需要具有进程外部名称的对象。一个未命名的管道只有在使用它的进程保持对管道的打开文件描述符时才存在。当进程退出并且操作系统关闭与进程关联的所有文件描述符时,未命名管道将关闭。

命名管道实际上是 FIFO。这些是由文件系统中的节点表示的持久对象。命名管道在一个或多个不一定相关且不需要同时存在的进程之间提供多对多、双向通信。管道的文件名用作通信进程之间的地址或合同。如果只有一个进程写入命名管道,而另一个进程从命名管道读取,则命名管道的行为方式与两个相关进程之间的未命名管道相同。

所以简短的回答是,您需要一个命名管道来在可能不同时存在的不相关进程之间进行通信。

  • @goldilocks:命名管道通常用作嵌入式系统中进程之间的内存驻留临时邮箱,其中通信进程是短暂的并且不是同时存在的。与共享内存 IPC 相比,其优势在于实现的简单性以及仅使用 RAM 的事实。缺点是引导之间的非持久性和管道的逐字节 FIFO 特性与使用具有共享内存的结构的能力相比。 (2认同)

Mar*_*iae 6

命名管道还有另一个优点:您可以跨不同系统使用它们。假设您想要在不同机器上运行的两个进程的实时通信。然后在两者之间共享一个文件夹,将您的 FIFO 放在文件夹中,然后就可以了。这比将设计用于处理文件的应用程序转换为侦听端口的服务要容易得多。


小智 5

其他地方没有提到的一个优点是命名管道可以用在只有文件才能做到的地方。

例如,某些电子邮件客户端具有将 ~/.signature 的内容附加到每个邮件消息的功能。如果 .signature 是一个命令行选项,或者如果邮件客户端能够注意到 .signature 是可执行的并运行它,那么您就不需要命名管道。但是如果邮件客户端不是那么复杂,您可以创建一个名为 .signature 的命名管道,并运行一个应用程序,每次读取文件时都会生成一个新签名。