52 POSIX 消息队列
和 System V 不同点:
消息按照优先级排序
消息按照优先级排序(数值越小越靠前)。每次接收都只能拿到开头的消息,不像 SysV 消息队列那样不按照优先级排序、且可以选择性获取中间的消息。
注册消息通知
POSIX 消息队列还有一个功能就是能够注册消息通知,以得到有消息来临的消息:
- 任何时候只能有一个进程可以注册特定队列的消息通知(第二个进程注册时会失败得到 EBUSY 错误)。进程也可以主动解除通知。
- 消息通知是一次性的,通知完成之后就会自动解除。
- 只有消息队列从空变成非空时,才可能有通知。在非空的状态下来消息是不会产生通知的,只能先清空再来消息才可以产生通知。
- 消息队列从空变成非空时,如果有其他因为调用
mq_receive()
而阻塞的进程,那么消息由其中的一个进程获取,而不会产生通知!!
API:
SYNOPSIS
#include <mqueue.h>
#include <signal.h> /* Definition of SIGEV_* constants */
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
sigevent
类型可以通过 system_data_types(7) 和 sigevent(7) 查到,它允许我们选择用一个自选信号通知,或者选择创建一个新线程处理通知(这个新线程要运行的函数由我们来指定)。
和 POSIX 消息队列相关的 Linux 特性
mqueue 虚拟文件系统
可以用 mount -t mqueue none /dev/mqueue
挂载 mqueue 虚拟文件系统。在我的系统上,这个文件系统已经存在于 /dev/mqueue 了,不需要手动挂载,通过 cat /proc/mounts
就能看到。
Tip
除了能够看到 /dev/mqueue 是 mqueue 文件系统之外,还能看到 /dev/shm 是 tmpfs 文件系统。
多路复用
消息队列描述符实际上是文件描述符,可以用 I/O 多路复用的 API(select/poll/epoll)来监听。
资源限制
MQ_PRIO_MAX
:消息的最大优先级。MQ_OPEN_MAX
:进程最多能打开的消息队列数量。Linux 没有这个限制,但是因为消息队列描述符被实现为文件描述符,所以受到进程可以打开的文件描述符数量限制。- msg_max:新创建消息队列可以选择的优先级上限(默认值 10)。
- msgsize_max:新创建消息队列可以选择的消息大小上限(默认值 8192,最小值 128,最大值 1048576,但可能随着内核版本会变化)。
- queues_max:系统上能创建消息队列的最大数量,默认为 256。