使用 POSIX 消息队列进行进程内通信

Posted

技术标签:

【中文标题】使用 POSIX 消息队列进行进程内通信【英文标题】:Using POSIX message queues for intra-process communication 【发布时间】:2020-06-11 19:12:37 【问题描述】:

我正在设计一个单进程多线程嵌入式 Linux 应用程序。该设计包括客户端-服务器子系统,其中一个工作线程接收其他线程在 POSIX 消息队列上发布的消息。

我需要队列表现出非阻塞发送和阻塞接收语义。我可以想到几种方法来实现上述目标: - 为发送和访问队列创建两个单独的消息队列描述 接收,即调用 mq_open 两次。这之后将设置 O_NONBLOCK 标志 将用于通过队列发送的描述。

指定阻塞行为并使用 mq_timedsend 代替 mq_send

指定阻塞行为并在 mq_send 之前调用 mq_getattr 以避免发送阻塞

第一个解决方案可能是首选的解决方案,但要使其工作,必须保证每次调用 mq_open 创建一个新的消息队列描述对象(我还假设进程中的线程可以使用多个这样的对象来执行同一队列上的操作)。

POSIX 似乎提供了这样的保证 (https://pubs.opengroup.org/onlinepubs/009695399/functions/mq_open.html) 但是 Linux 文档并没有明确说明每次调用 mq_open 都会创建一个新的消息队列描述对象。

Linux有这样的保证吗?

谢谢,

【问题讨论】:

这听起来像数据报 unix 域套接字会更合适。由于这都是一个进程,您可以使用socketpair() 创建一对匿名的双向套接字来使用。或者只是一个无锁队列数据结构。 你考虑过 ZeroMQ 吗?使用inproc 传输意味着它可以避免将数据复制进/出内核,因此它可能比 Posix 消息队列更快。它还具有人们可能需要的所有语义/传输/模式。 【参考方案1】:

我需要队列表现出非阻塞发送和阻塞接收语义。

您可以在具有过期超时的阻塞队列上使用mq_timedsend(例如abs_timeout0, 0),当队列已满时,调用会立即返回(而不是阻塞)。


我正在设计一个单进程多线程嵌入式 Linux 应用程序。该设计包括客户端-服务器子系统,其中一个工作线程接收其他线程在 POSIX 消息队列上发布的消息。

消息队列将数据复制到内核并返回。不需要在同一进程中的线程之间进行通信。您可以只使用带有互斥体和条件变量的队列,这类似于内核在使用消息队列时为您所做的事情,但是使用您自己的队列可以避免将数据复制到内核中并返回。

我需要队列表现出非阻塞发送和阻塞接收语义。

非阻塞mq_send仅表示队列满时不阻塞。

The kernel protects the message queue with a spinlock internally 并且自旋锁被锁定在mq_sendmq_receive 上,因此从并发数据结构的角度来看,POSIX 消息队列是一个阻塞数据结构。

【讨论】:

以上是关于使用 POSIX 消息队列进行进程内通信的主要内容,如果未能解决你的问题,请参考以下文章

POSIX消息队列

POSIX消息队列

进程间通信——消息队列

使用 POSIX 消息队列运行 JNA 示例

进程间通信方式

TLPI读书笔记第51章-POSIX IPC介绍