比较Unix / Linux IPC


78

Unix / Linux提供了许多IPC:管道,套接字,共享内存,dbus,消息队列...

每种应用最适合的应用是什么,它们的性能如何?


1
dbus是在其他IPC类型的顶部实现的:unix域套接字,TCP / IP和管道远不止……
Maygarden法官09年

Answers:


100

Unix IPC

以下是七大公司:

  1. 仅在与父/子相关的进程中有用。致电pipe(2)fork(2)。单向。

  2. FIFO或命名管道

    与普通管道不同,两个不相关的进程可以使用FIFO。致电mkfifo(3)。单向。

  3. 套接字Unix域套接字

    双向的。用于网络通信,但也可以在本地使用。可以用于不同的协议。TCP没有消息边界。致电socket(2)

  4. 消息队列

    操作系统维护离散消息。见SYS / msg.h

  5. 信号

    信号将整数发送到另一个进程。与多线程不能很好地配合。致电kill(2)

  6. 信号

    用于多进程或线程的同步机制,类似于排队等候洗手间的人。见SYS / sem.h中

  7. 共享内存

    做自己的并发控制。致电shmget(2)

邮件边界问题

选择一种方法而不是另一种方法时,一个决定因素是消息边界问题。您可能希望“消息”彼此分离,但不是像TCP或Pipe这样的字节流。

考虑一对回显客户端和服务器。客户端发送字符串,服务器接收它,然后立即将其发送回去。假设客户端发送“ Hello”,“ Hello”和“答案如何?”。

使用字节流协议,服务器可以接收“ Hell”,“ oHelloHow”和“关于答案?”等信息;或者更实际的是“ HelloHello答案如何?”。服务器不知道消息边界在哪里。

一个古老的技巧是将消息长度限制为CHAR_MAXUINT_MAX并同意先在char或中发送消息长度uint。因此,如果您在接收方,则必须先阅读消息长度。这也意味着一次只能有一个线程进行消息读取。

使用UDP或消息队列之类的离散协议,您不必担心此问题,但是以编程方式字节流更易于处理,因为它们的行为类似于文件和stdin / out。


我猜您可以在其中包含信号灯,但是我将其更多地看作是并发工具,而不是进程间通信工具。
Eugene Yokota

2
顺便说一句,您可以通过Unix域套接字[ linux.die.net/man/7/unix]
Hasturkun

2
一个较小的优点:pipe(2)也可用于同级进程中-例如,shell是管道中所有进程的父级。
哈德森,2009年

5
请注意,您可以具有面向消息的Unix域套接字。与互联网不同,它们是可靠的。
汤姆·安德森

2
这些方法是否有基准或定性性能比较?
kakyo

17

共享内存可能是最有效的,因为您需要在共享内存的基础上构建自己的通信方案,但是它需要大量的维护和同步。解决方案也可用于将共享内存分配给其他计算机。

如今,套接字是最便携的,但是比管道需要更多的开销。能够在本地或通过网络透明地使用套接字的功能是一大优势。

消息队列和信号对于硬实时应用程序可能非常有用,但它们并不那么灵活。

这些方法自然是为流程之间的通信而创建的,并且在流程中使用多个线程会使事情(尤其是信号)复杂化。


以我的经验,命名管道可以比几乎任何其他方法都快,并且更安全。
Erik Aronesty '16

10

这是带有简单基准的网页:https : //sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets

据我所知,每个都有其优点:

  • 管道I / O是最快的,但需要父子关系才能工作。
  • Sysv IPC具有定义的消息边界,可以在本地连接不同的进程。
  • UNIX套接字可以在本地连接不同的进程,并具有更高的带宽,但没有固有的消息边界。
  • TCP / IP套接字可以连接任何进程,甚至可以通过网络进行连接,但是开销更高,并且没有固有的消息边界。


如何比较dbus和其他?
BЈовиat

DBUS使用这些机制中的一种或几种。在他们自己的称为DBUS1(或KDBUS ...)的IPC机制上,有一些长期的工作,但是仍然没有被合并到主线内核中。
菲利普·惠兰

8

值得注意的是,许多库在另一种之上实现了一种类型的事物。

共享内存不需要使用可怕的sysv共享内存功能-使用mmap()更为优雅(如果要将文件命名为tmpfs / dev / shm,则将文件映射到tmpfs / dev / shm上;如果需要,将mmap / dev / zero映射为分叉未执行的进程以匿名方式继承它)。话虽如此,它仍然使您的进程需要一些同步以避免问题的发生-通常是通过使用其他一些IPC机制对共享内存区域的访问进行同步。


我以前从未听说过映射/ dev / zero。巧妙!您提到它只能与子项共享-但是可以通过Unix域套接字使用cmsg / SCM_RIGHTS将正在使用的文件描述符发送到不相关的进程,并在那里获得共享映射吗?还是您继承的映射,而不是文件描述符?即使它确实起作用,您仍需要在文件系统中的某个位置进行套接字,因此即使映射是匿名的,用于设置它的套接字也不是。GUH。IPC很难。我们去买东西吧!
汤姆·安德森

mmaping / dev / zero实际上由某种内存分配使用。但是优点是,如果使用MAP_SHARED,它将与fork()子进程共享(通常在逻辑上复制内存)。您可以与一个无关的过程共享它吗?我不这么认为。我怀疑mmap()调用需要共享,而不是文件描述符。
MarkR 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.