我正在阅读有关各种IPC机制的资料。我试图找出使用共享内存和命名管道(FIFO)的场景。
管道: 多个进程可以写入,但只有一个进程可以读取。写操作是原子的。
共享内存: 多个进程可以读写。用户需要为读写提供互斥。
这是使用共享内存和管道的唯一区别吗?
我正在阅读有关各种IPC机制的资料。我试图找出使用共享内存和命名管道(FIFO)的场景。
管道: 多个进程可以写入,但只有一个进程可以读取。写操作是原子的。
共享内存: 多个进程可以读写。用户需要为读写提供互斥。
这是使用共享内存和管道的唯一区别吗?
本质上,管道 - 无论是命名的还是匿名的 - 就像消息传递一样使用。某人向接收者发送信息,接收者可以接收它。共享内存更像发布数据 - 某人将数据放入共享内存中,读者(可能很多)必须使用同步,例如通过信号量来了解有新数据的事实,并且必须知道如何读取内存区域以查找信息。
对于管道,同步是简单的,并且内置于管道机制本身中-当发生有趣的事情时,您的读取和写入将冻结和解冻应用程序。对于共享内存,更容易异步工作并仅偶尔检查新数据-但代价是更复杂的代码。此外,你可以得到多对多通信,但又需要更多的工作。而且,由于上述原因,基于管道的通信的调试比共享内存更容易。
一个小差异是:管道在文件系统中直接可见,而共享内存区域需要特殊工具(例如ipcs
)进行管理,以防您创建了共享内存段,但您的应用程序死亡并且没有清理自己(同样适用于信号量和许多其他同步机制,您可能需要与共享内存一起使用)。
共享内存还可以让您更好地控制缓冲和资源使用-在操作系统允许的限制范围内,您决定分配多少内存以及如何使用它。对于管道,操作系统自动控制事物,因此再次失去了一些灵活性,但减轻了很多工作。
最重要的要点总结:管道用于一对一通信,编码较少且让操作系统处理事物;共享内存用于多对多通信,具备更多手动控制的优势,但需要更多的工作和较难的调试。
pipe
系统调用匿名创建。共享内存也可以通过不私有地nmap
文件来驻留在文件系统中。 - johannespipe(7)
函数确实说明了如果O_NONBLOCK未被禁用并且要写入的字节数小于PIPE_BUF,则调用write(2)
是根据POSIX.1-2001标准保证原子性的。但是,同样的手册中也建议“不同的实现对管道容量有不同的限制。应用程序不应依赖特定容量”。因此,在特定情况下,多个写入者的方案确实可行,但如果没有很好的理由,我不会基于此构建应用程序。你永远不知道你可能需要什么大小的消息。 - Michał Kosmulski