与无名管道相比,使用命名管道有哪些优点?

与无名管道相比,使用命名管道有哪些优点?

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

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

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

答案1

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

  • 您不必同时启动读/写过程
  • 你可以有多个读者/作者不需要共同的血统
  • 作为一个文件,您可以控制所有权和权限
  • 它们是双向的、无名管道可能是单向的 *

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

(已更新,感谢反馈斯蒂芬·查泽拉斯

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

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

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

命名管道的功能与 TCP 连接没有什么不同,但也有重要的区别。因为 fifo 有一个持久的文件系统名称,所以即使没有读取器,您也可以写入它,诚然,写入会阻塞(没有异步或非阻塞 I/O),但如果接收器不存在,则不会丢失数据已启动(或正在重新启动)。

作为参考,另请参阅Unix 域套接字,以及答案这个 Stackoverflow 问题其中总结了主要内容工控机方法,以及这个其中谈到popen()

答案2

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

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

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

答案3

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

答案4

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

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

相关内容