何时使用管道与何时使用共享内存

vam*_*msi 27 linux ipc pipe shared-memory

我正在阅读各种IPC机制.我试图弄清楚场景,我们使用共享内存和我们使用命名管道(FIFO)的地方.

管道:多个进程可以写入,但只有一个进程可以读取.写操作是原子的.

共享内存:多个进程可以读写.并且用户还需要提供互斥以进行读写.

这是共享内存和管道应用的唯一区别吗?

Mic*_*ski 51

从本质上讲,管道 - 无论是命名还是匿名 - 都像消息传递一样使用.有人向收件人发送一条信息,收件人可以收到.共享内存更像是发布数据 - 有人将数据放入共享内存中,而读者(可能很多)必须使用同步,例如通过信号量来了解有新数据的事实,并且必须知道如何读取内存区域以查找信息.

使用管道,同步很简单并且内置于管道机制本身 - 当有趣的事情发生时,您的读取和写入将冻结并解冻应用程序.使用共享内存,可以更容易地异步工作并且偶尔检查一次新数据 - 但代价是更复杂的代码.此外,您可以获得多对多的通信,但它需要更多的工作.此外,由于上述原因,基于管道的通信调试比调试共享内存更容易.

一个小的区别是,fifos直接在文件系统中可见,而共享内存区域需要特殊的工具,如ipcs他们的管理,以防你创建一个共享的内存段,但你的应用程序死了,并且不会自行清理(信号量和信号量相同)许多其他同步机制,您可能需要与共享内存一起使用).

共享内存还使您可以更好地控制缓冲区和资源使用 - 在操作系统允许的限制范围内,您决定分配多少内存以及如何使用它.使用管道,操作系统会自动控制事物,因此您再次失去了一些灵活性,但却放松了很多工作.

最重要的要点摘要:用于一对一通信的管道,更少的编码和让操作系统处理的东西,用于多对多的共享内存,更多的手动控制,但代价是更多的工作和更难的调试.

  • @MarkRajcok你是对的,`pipe(7)`的人确实声明如果禁用O_NONBLOCK并且要写入的字节数小于PIPE_BUF,则对每个POSIX保证调用`write(2)`是原子的. 1-2001.另一方面,同一手册页包含的建议是"不同的实现对管道容量有不同的限制.应用程序不应该依赖于特定的容量".因此,对于特定情况,多作者场景确实会起作用,但我不会在没有充分理由的情况下将应用程序基于它.您永远不知道有时可能需要的邮件大小. (4认同)
  • FIFO也支持多对一通信("摘要"仅暗示一对一). (3认同)
  • 一些小的修正。管道也可以通过 `pipe` 系统调用匿名创建。共享内存也可以通过不私下“nmap”文件来驻留在文件系统中。 (2认同)
  • @MarkRajcok 虽然可能,但实际上让许多具有管道的编写器并不是很有用,因为没有内置机制来管理消息级别的同步-所有编写器发送的任何内容都将以不可预测的方式交错。即使实现了外部同步,最好的办法是在发送每条消息时在写入者之间进行独占锁定,这是无效的,因为只能同时写入一个。 (2认同)
  • 如果消息总是小于PIPE_BUF,我认为您不需要实现自己的锁定 - 消息不会交错.也许我应该说"与PIPE_BUF尺寸限制多对一". (2认同)