80

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

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

4

4 回答 4

105

Unix IPC

以下是七大:

  1. 管道

    仅在与父/子相关的进程中有用。呼叫pipe(2)fork(2)。单向。

  2. FIFO或命名管道

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

  3. 套接字Unix 域套接字

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

  4. 消息队列

    操作系统维护离散消息。请参阅sys/msg.h

  5. 信号

    Signal 向另一个进程发送一个整数。不能很好地与多线程啮合。打电话kill(2)

  6. 信号

    一种多进程或多线程的同步机制,类似于排队等候洗手间的人。请参阅sys/sem.h

  7. 共享内存

    做你自己的并发控制。打电话shmget(2)

消息边界问题

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

考虑一对回显客户端和服务器。客户端发送字符串,服务器接收并立即发送回。假设客户端发送“Hello”、“Hello”和“How about an answer?”。

使用字节流协议,服务器可以接收“Hell”、“oHelloHow”和“about an answer?”;或者更现实地说“你好你好,答案怎么样?”。服务器不知道消息边界在哪里。

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

使用 UDP 或消息队列等离散协议,您不必担心这个问题,但以编程方式处理字节流更容易,因为它们的行为类似于文件和标准输入/输出。

于 2009-01-01T06:09:13.500 回答
17

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

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

消息队列和信号非常适合硬实时应用程序,但它们没有那么灵活。

这些方法自然是为进程之间的通信而创建的,在一个进程中使用多个线程会使事情变得复杂——尤其是信号。

于 2009-01-01T06:14:28.980 回答
10

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

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

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

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

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

于 2009-01-01T21:39:19.067 回答