在Linux上广播IPC

Broadcast IPC on Linux

本文关键字:IPC 广播 Linux      更新时间:2023-10-16

我对Linux上的IPC机制有以下要求:

  1. 有一个生产者过程,但是多个消费者流程。消费者过程不是生产者过程的孩子。他们是独立长大的。

  2. 传输的消息是固定尺寸的POD结构。

  3. 我们需要为此机制使用固定数量的内存。像机制之类的环缓冲区似乎是理想的。

  4. 生产者需要非常快地运行,并且永远无法等待消费者。相反,它需要覆盖固定尺寸缓冲区(用于IPC)中的条目,并且消费者需要检测此问题,并在周围缠绕的情况下跳过中间消息来赶上生产者。

  5. 消费者可以随时出现并下降,并且在单一生产商和短暂的消费者出现时,应该没有明确的握手。因此,当消费者出现时,他们只是开始从可用的最新消息中阅读,并在他们想要的情况下掉下来,而无需生产者知道。

我现在有以下解决方案:

  1. 我正在创建一个固定尺寸条目的环缓冲区,该缓冲区由一个过程编写并由许多过程读取。环缓冲区构建在/tmp中的内存映射文件的顶部。

  2. 环缓冲区代码使得生产者永远不会阻止等待任何消费者消费条目。取而代之的是,消费者检测到戒指缓冲区何时在阅读/处理条目的中间包裹,并赶上最新信息。我使用几个生产者序列来做。如果需要,我可以对此进行扩展,但似乎并不相关。因此,生产商全速疾驰,消费者落后于发现中读腐败并跳过最新条目。

到目前为止,这很好。现在,我试图弄清楚如何在混音中添加一些信号,以便消费者不必旋转阅读生产者序列等待新消息。我对信号部分还有一些其他要求:

  1. 信号需要是某种广播机制。这是一个生产者/多个consumers的要求。因此,当生产商发出信号时,应该能够唤醒多个过程。鉴于生产者不了解任何消费者,似乎我们需要某种命名资源来执行此信号。

  2. 信号传导机制需要与其他常规信号相结合,这些信号可以在使用select/epoll_wait时等待。读取形式的消费者这种IPC机制/ring_buffer正在等待写入其他无关的管道/插座等,他们在这些FD上使用选择。能够从这种机制中产生FD是理想的选择,消费者可以将其添加到他们的选择中。同样,如果消费者正在等待多个这样的ring_buffers,我们需要能够阻止所有这些铃声并在任何一个信号发出信号时醒来。

考虑到这些要求,我消除了一些选择:

  1. 条件变量:我们不能从消费者身上阻止其中的多个。他们也不是selectable

  2. 命名管道:我们需要每个消费者的命名管道,这意味着我们要避免的某种生产者/消费者握手。

  3. eventfd:eventfds未命名,因此似乎只是在父母和子女过程之间的信号时才是解决方案。我的场景具有独立启动的过程。

  4. Unix域插座:这里似乎没有任何广播设施,因此我不确定如果没有明确的套接字,每个消费者都可以正常工作。这违背了无握手的要求。

我有点损失,看不到其他好选择。对我来说,UDP多播可能会起作用。消费者都可以成为多播组的一部分(使用SO_REUSEADDR创建套接字),唯一的生产商可以在该组上发送消息以发出消费者的信号。但这似乎真的很重,精心制作。还有其他好的机制可以实现这一目标吗?我愿意与Futex API直接合作,只要它可以使用SELECT/EPOLL在其他无关的FD上封锁。

我建议通过dbus发送信号。当您可以使用已经可以执行您想要的成熟框架时,为什么要滚动自己的IPC?

此页面应该让您入门:

https://dbus.freedesktop.org/doc/dbus-tutorial.html

最后,它包括指向QT和GLIB API的链接。我既没有使用过,而是在低级API周围编写自己的Boost.asio包装器,尽管这是一项相当涉及的工作。

https://dbus.freedesktop.org/doc/api/html/

顺便说一句,为了发送二进制数据块,您需要将DBUS_TYPE_BYTE类型的DBUS_TYPE_ARRAY类型的ARG附加到您的消息中。请注意,DBUS_TYPE_STRING不能包含零字节或无效的Unicode序列。

更新:最近引起我注意的另一个库称为SD-BUS。这是一个很好的概述&教程:

http://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html