【问题标题】:Comparing Unix/Linux IPC比较 Unix/Linux IPC
【发布时间】:2010-09-29 02:38:08
【问题描述】:

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

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

【问题讨论】:

标签: linux unix ipc


【解决方案1】:

Unix IPC

这是七大:

  1. Pipe

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

  2. FIFO,或命名管道

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

  3. SocketUnix Domain Socket

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

  4. Message Queue

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

  5. Signal

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

  6. Semaphore

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

  7. Shared memory

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

消息边界问题

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

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

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

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

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

【讨论】:

  • 我猜你可以在其中包含信号量,但我认为它更像是并发工具而不是进程间通信工具。
  • 顺便说一句,您可以通过 Unix 域套接字发送文件描述符 [linux.die.net/man/7/unix]
  • 一个小问题:pipe(2) 也可以在兄弟进程中使用——例如,shell 是管道中所有进程的父进程。
  • 请注意,您可以拥有面向消息的 unix 域套接字。与互联网的不同,它们是可靠的。
  • 这些方法是否有基准或定性性能比较?
【解决方案2】:

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

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

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

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

【讨论】:

  • 根据我的经验,命名管道可以和几乎任何其他方法一样快,并且更安全。
【解决方案3】:

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

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

【讨论】:

  • 我以前从未听说过映射 /dev/zero。巧妙!您提到它只能与孩子共享 - 但是您可以通过 unix 域套接字使用 cmsg/SCM_RIGHTS 将您正在使用的文件描述符发送到不相关的进程,并最终在那里获得共享映射吗?还是您继承的映射,而不是文件描述符?即使它确实有效,您仍然需要文件系统中某处的套接字来执行此操作,因此即使映射是匿名的,用于设置它的套接字也不是。嗯。 IPC 很难。我们去购物吧!
  • mmaping /dev/zero 实际上被某些类型的内存分配使用。但优点是,如果您使用 MAP_SHARED,它会与您的 fork() 子进程共享(通常内存是逻辑复制的)。你能与一个不相关的过程分享它吗?我不这么认为。我怀疑 mmap() 调用需要共享,而不是文件描述符。
【解决方案4】:

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

据我所知,各有优势:

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

【讨论】:

猜你喜欢
  • 2011-02-20
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
相关资源
最近更新 更多