比较 Unix/Linux IPC

发布于 2024-07-10 19:57:23 字数 83 浏览 4 评论 0原文

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

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

Lots of IPCs are offered by Unix/Linux: pipes, sockets, shared memory, dbus, message-queues...

What are the most suitable applications for each, and how do they perform?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最后的乘客 2024-07-17 19:57:23

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 等字节流。

考虑一对 echo 客户端和服务器。 客户端发送字符串,服务器接收它并立即发回。 假设客户端发送“你好”、“你好”和“回答怎么样?”。

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

一个古老的技巧是将消息长度限制为 CHAR_MAXUINT_MAX 并同意首先以 charuint 形式发送消息长度。 所以,如果你在接收端,你必须先读取消息长度。 这也意味着一次只能有一个线程执行消息读取。

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

Unix IPC

Here are the big seven:

  1. Pipe

    Useful only among processes related as parent/child. Call pipe(2) and fork(2). Unidirectional.

  2. FIFO, or named pipe

    Two unrelated processes can use FIFO unlike plain pipe. Call mkfifo(3). Unidirectional.

  3. Socket and Unix Domain Socket

    Bidirectional. Meant for network communication, but can be used locally too. Can be used for different protocol. There's no message boundary for TCP. Call socket(2).

  4. Message Queue

    OS maintains discrete message. See sys/msg.h.

  5. Signal

    Signal sends an integer to another process. Doesn't mesh well with multi-threads. Call kill(2).

  6. Semaphore

    A synchronization mechanism for multi processes or threads, similar to a queue of people waiting for bathroom. See sys/sem.h.

  7. Shared memory

    Do your own concurrency control. Call shmget(2).

Message Boundary issue

One determining factor when choosing one method over the other is the message boundary issue. You may expect "messages" to be discrete from each other, but it's not for byte streams like TCP or Pipe.

Consider a pair of echo client and server. The client sends string, the server receives it and sends it right back. Suppose the client sends "Hello", "Hello", and "How about an answer?".

With byte stream protocols, the server can receive as "Hell", "oHelloHow", and " about an answer?"; or more realistically "HelloHelloHow about an answer?". The server has no clue where the message boundary is.

An age old trick is to limit the message length to CHAR_MAX or UINT_MAX and agree to send the message length first in char or uint. So, if you are at the receiving side, you have to read the message length first. This also implies that only one thread should be doing the message reading at a time.

With discrete protocols like UDP or message queues, you don't have to worry about this issue, but programmatically byte streams are easier to deal with because they behave like files and stdin/out.

本宫微胖 2024-07-17 19:57:23

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

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

消息队列和信号对于硬实时应用程序来说非常有用,但它们不够灵活。

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

Shared memory can be the most efficient since you build your own communication scheme on top of it, but it requires a lot of care and synchronization. Solutions are available for distributing shared memory to other machines too.

Sockets are the most portable these days, but require more overhead than pipes. The ability to transparently use sockets locally or over a network is a great bonus.

Message queues and signals can be great for hard real-time applications, but they are not as flexible.

These methods were naturally created for communication between processes, and using multiple threads within a process can complicate things -- especially with signals.

一笔一画续写前缘 2024-07-17 19:57:23

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

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

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

Here is a webpage with a simple benchmark: https://sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets

As far as I can tell, each has their advantages:

  • Pipe I/O is the fastest but needs a parent/child relationship to work.
  • Sysv IPC has a defined message boundary and can connect disparate processes locally.
  • UNIX sockets can connect disparate processes locally and has higher bandwidth but
    no inherent message boundaries.
  • TCP/IP sockets can connect any processes, even over the network but has higher overhead
    and no inherent message boundaries.
以往的大感动 2024-07-17 19:57:23

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

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

It's worth noting that lots of libraries implement one type of thing on top of another.

Shared memory doesn't need to use the horrible sysv shared memory functions - it's much more elegant to use mmap() (mmap a file in on a tmpfs /dev/shm if you want it named; mmap /dev/zero if you want forked not exec'd processes to inherit it anonymously). Having said that, it still leaves your processes with some need for synchronisation to avoid problems - typically by using some of the other IPC mechanisms to do synchronisation of access to a shared memory area.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文