【发布时间】:2017-02-15 02:15:28
【问题描述】:
我对 Linux 上的 IPC 机制有以下要求:
有一个生产者进程,但有多个消费者进程。消费者进程不是生产者进程的子进程。他们是独立长大的。
正在传输的消息是固定大小的 POD 结构。
我们需要为此机制使用固定数量的内存。类似环形缓冲区的机制在这里似乎很理想。
生产者需要运行得非常快,不能等待消费者。相反,它需要覆盖固定大小缓冲区(用于 IPC)中的条目,而消费者需要检测到这个问题,并通过跳过中间消息来赶上生产者,以防发生回绕。
消费者可以随时上下,在单个生产者和临时消费者之间不应该有明确的握手,因为他们上下。因此,当消费者上来时,他们只是从可用的最新消息开始阅读,然后在生产者不知道的情况下随时下课。
我现在有以下解决方案:
我正在创建一个由一个进程写入并由多个进程读取的固定大小条目的环形缓冲区。环形缓冲区建立在 /tmp 中的内存映射文件之上。
环形缓冲区代码使得生产者永远不会阻塞等待任何消费者消费条目。相反,消费者在读取/处理条目的过程中检测到环形缓冲区何时回绕,然后赶上最新的。我用几个生产者序列来做。如果需要,我可以对此进行扩展,但似乎不太相关。因此,生产者全速奔跑,落后的消费者检测到中间读取损坏并跳到最新条目。
到目前为止,这工作正常。现在我试图弄清楚如何在混合中添加一些信号,这样消费者就不必旋转读取生产者序列来等待新消息。我对信号部分有一些额外的要求:
信令需要是某种广播机制。这遵循一个生产者/多个消费者的要求。因此,当生产者发出信号时,应该能够唤醒多个进程。鉴于生产者不知道任何消费者,似乎我们需要某种命名资源来执行此信号。
信号机制需要与其他可以使用 select/epoll_wait 等待的常规信号组合。正在读取此 IPC 机制/ring_buffer 的消费者正在等待对其他不相关管道/套接字等的写入,并且他们在这些 FD 上使用选择。理想的情况是能够从这种机制中生成一个 FD,消费者可以将其添加到他们的 select 调用中。同样,如果消费者正在等待多个这样的 ring_buffers,我们需要能够阻止所有这些,并在其中任何一个发出信号时立即唤醒。
考虑到这些要求,我排除了几个选项:
条件变量:我们不能阻止消费者中的多个。他们也不是
selectable。命名管道:我们需要每个消费者都有一个命名管道,这意味着我们希望避免某种生产者/消费者握手。
eventfd: eventfds 没有命名,所以如果信号是在父进程和子进程之间,它们似乎只是一种解决方案。我的场景有独立启动的进程。
Unix 域套接字:这里似乎没有任何广播设施,所以我不确定如果没有每个消费者的明确套接字,这是否可以工作。这违反了不握手的要求。
我有点茫然,看不到任何其他好的选择。在我看来,UDP 多播可能会起作用。消费者都可以是多播组的一部分(使用SO_REUSEADDR 创建套接字),并且唯一的生产者可以在该组上发送消息以向消费者发送信号。但这似乎真的很沉重和精心制作。有没有其他好的机制来实现这一点?我愿意直接与Futex API 合作,只要它有助于使用 select/epoll 阻止其他不相关的 FD。
【问题讨论】:
标签: c++ linux ipc multiprocess