MQ_OVERVIEW - Linux手册页
Linux程序员手册 第7部分
更新日期: 2020-06-09
名称
mq_overview-POSIX消息队列概述
说明
POSIX消息队列允许进程以消息的形式交换数据。此API与System V消息队列(msgget(2),msgsnd(2),msgrcv(2)等)提供的API不同,但是提供了类似的功能。
消息队列是使用mq_open(3)创建和打开的;此函数返回消息队列描述符(mqd_t),该描述符用于在以后的调用中引用打开的消息队列。每个消息队列由/ somename形式的名称标识;也就是说,一个以NULL结尾的字符串,最多NAME_MAX(即255个)字符,由一个初始斜杠组成,后跟一个或多个字符(都不是斜杠)。通过将相同的名称传递给mq_open(3),两个进程可以在同一队列上进行操作。
使用mq_send(3)和mq_receive(3)在队列之间来回传送消息。当进程使用完队列后,可以使用mq_close(3)关闭该队列,而当不再需要该队列时,可以使用mq_unlink(3)将其删除。可以使用mq_getattr(3)和mq_setattr(3)检索和修改队列属性(在某些情况下)。进程可以使用mq_notify(3)请求异步通知消息到达先前为空的队列。
消息队列描述符是对打开的消息队列描述的引用(请参见open(2))。在fork(2)之后,子级继承其父级消息队列描述符的副本,并且这些描述符与父级中相应的消息队列描述符引用相同的打开消息队列描述。两个进程中的相应消息队列描述符共享与打开的消息队列描述关联的标志(mq_flags)。
每个消息都具有关联的优先级,并且始终将消息始终首先传递到接收过程的最高优先级。消息优先级范围从0(低)到sysconf(_SC_MQ_PRIO_MAX)-1(高)。在Linux上,sysconf(_SC_MQ_PRIO_MAX)返回32768,但是POSIX.1仅要求实现至少支持0到31范围内的优先级;一些实现仅提供此范围。
本节的其余部分描述了POSIX消息队列的Linux实现的一些特定细节。
Library interfaces and system calls
在大多数情况下,上面列出的mq _ *()库接口是在同名的基础系统调用之上实现的。下表列出了与该方案的差异:
- <b>库接口系统调用</b><a href="../man3/mq_close.3.html">mq_close</a>(3)<a href="../man2/close.2.html">close</a>(2) <a href="../man3/mq_getattr.3.html">mq_getattr</a>(3)<a href="../man2/mq_getsetattr.2.html">mq_getsetattr</a>(2) <a href="../man3/mq_notify.3.html">mq_notify</a>(3)<a href="../man2/mq_notify.2.html">mq_notify</a>(2) <a href="../man3/mq_open.3.html">mq_open</a>(3)<a href="../man2/mq_open.2.html">mq_open</a>(2) <a href="../man3/mq_receive.3.html">mq_receive</a>(3)<a href="../man2/mq_timedreceive.2.html">mq_timedreceive</a>(2) <a href="../man3/mq_send.3.html">mq_send</a>(3)<a href="../man2/mq_timedsend.2.html">mq_timedsend</a>(2) <a href="../man3/mq_setattr.3.html">mq_setattr</a>(3)<a href="../man2/mq_getsetattr.2.html">mq_getsetattr</a>(2) <a href="../man3/mq_timedreceive.3.html">mq_timedreceive</a>(3)<a href="../man2/mq_timedreceive.2.html">mq_timedreceive</a>(2) <a href="../man3/mq_timedsend.3.html">mq_timedsend</a>(3)<a href="../man2/mq_timedsend.2.html">mq_timedsend</a>(2) <a href="../man3/mq_unlink.3.html">mq_unlink</a>(3)<a href="../man2/mq_unlink.2.html">mq_unlink</a>(2)
Versions
从内核2.6.6开始,Linux就已经支持POSIX消息队列。自版本2.3.4起已提供Glibc支持。
Kernel configuration
可以通过CONFIG_POSIX_MQUEUE内核配置选项来配置对POSIX消息队列的支持。默认情况下启用此选项。
Persistence
POSIX消息队列具有内核持久性:如果未由mq_unlink(3)删除,则消息队列将一直存在,直到系统关闭。
Linking
使用POSIX消息队列API的程序必须使用cc -lrt进行编译,以链接到实时库librt。
/proc interfaces
以下接口可用于限制POSIX消息队列占用的内核内存量,以及设置新消息队列的默认属性:
- /proc/sys/fs/mqueue/msg_default(since Linux 3.5)
- 当通过调用mq_open(3)(其中attr指定为NULL)创建队列时,此文件定义用于新队列的mq_maxmsg设置的值。该文件的默认值为10。最小值和最大值与/ proc / sys / fs / mqueue / msg_max相同。新队列的默认mq_maxmsg值将是msg_default和msg_max中的较小者。直到Linux 2.6.28,默认的mq_maxmsg为10;默认值为10。从Linux 2.6.28到Linux 3.4,默认值是为msg_max限制定义的值。
- /proc/sys/fs/mqueue/msg_max
- 该文件可用于查看和更改队列中最大邮件数的上限。此值充当赋予mq_open(3)的attr->mq_maxmsg参数的上限。 msg_max的默认值为10。最小值为1(2.6.28之前的内核中为10)。上限为HARD_MSGMAX。对于特权进程(CAP_SYS_RESOURCE),将忽略msg_max限制,但是仍然会施加HARD_MSGMAX上限。
- The definition of
HARD_MSGMAX
has changed across kernel versions:
- *
- 最高Linux 2.6.32:131072 / sizeof(void *)
- *
- Linux 2.6.33至3.4:(32768 * sizeof(void *)/ 4)
- *
- 从Linux 3.5开始:65,536
- /proc/sys/fs/mqueue/msgsize_default(since Linux 3.5)
- 当通过调用mq_open(3)(其中attr指定为NULL)创建队列时,此文件定义用于新队列的mq_msgsize设置的值。该文件的默认值为8192(字节)。最小值和最大值与/ proc / sys / fs / mqueue / msgsize_max相同。如果msgsize_default超过msgsize_max,则新队列的默认mq_msgsize值将限制为msgsize_max限制。直到Linux 2.6.28,默认的mq_msgsize为8192;从Linux 2.6.28到Linux 3.4,默认值为为msgsize_max限制定义的值。
- /proc/sys/fs/mqueue/msgsize_max
- This file can be used to view and change the ceiling on the
maximum message size.
This value acts as a ceiling on the
attr->mq_msgsize
argument given to
mq_open(3).The default value for
msgsize_maxis 8192 bytes.
The minimum value is 128 (8192 in kernels before 2.6.28).
The upper limit for
msgsize_maxhas varied across kernel versions:
- *
- 在Linux 2.6.28之前,上限为INT_MAX。
- *
- 从Linux 2.6.28到3.4,限制为1,048,576。
- *
- 从Linux 3.5开始,限制为16,777,216(HARD_MSGSIZEMAX)。
- 对于特权进程(CAP_SYS_RESOURCE),将忽略msgsize_max限制,但是,从Linux 3.5开始,对特权进程强制执行HARD_MSGSIZEMAX上限。
- /proc/sys/fs/mqueue/queues_max
- 此文件可用于查看和更改系统范围内可以创建的消息队列数量的限制。 queues_max的默认值为256。queues_max限制没有上限。特权进程(CAP_SYS_RESOURCE)可以超过限制(但请参见BUGS)。
Resource limit
RLIMIT_MSGQUEUE资源限制在getrlimit(2)中进行了描述,该资源限制对属于进程的真实用户ID的所有消息队列可以占用的空间量进行了限制。
Mounting the message queue filesystem
在Linux上,消息队列是在虚拟文件系统中创建的。 (其他实现也可能提供这种功能,但是细节可能会有所不同。)可以使用以下命令(由超级用户)挂载此文件系统:
# mkdir /dev/mqueue # mount -t mqueue none /dev/mqueue
粘贴位在安装目录上自动启用。
挂载文件系统后,可以使用通常用于文件的命令(例如ls(1)和rm(1))查看和操纵系统上的消息队列。
目录中每个文件的内容由一行包含有关队列的信息组成:
$ cat /dev/mqueue/mymq QSIZE:129 NOTIFY:2 SIGNO:0 NOTIFY_PID:8260
这些字段如下:
- QSIZE
- 队列中所有消息中的数据字节数(但请参阅BUGS)。
- NOTIFY_PID
- 如果它不为零,则具有此PID的进程已使用mq_notify(3)注册异步消息通知,其余字段描述了通知如何发生。
- NOTIFY
- 通知方法:0为SIGEV_SIGNAL; 1是SIGEV_NONE; 2是SIGEV_THREAD。
- SIGNO
- 用于SIGEV_SIGNAL的信号编号。
Linux implementation of message queue descriptors
在Linux上,消息队列描述符实际上是文件描述符。 (POSIX不需要这样的实现。)这意味着可以使用select(2),poll(2)或epoll(7)监视消息队列描述符。这不是便携式的。
在mq_open(2)返回的文件描述符上自动设置close-on-exec标志(请参见open(2))。
IPC namespaces
有关POSIX消息队列对象和IPC名称空间的交互的讨论,请参见ipc_namespaces(7)。
备注
System V消息队列(msgget(2),msgsnd(2),msgrcv(2)等)是用于在进程之间交换消息的较旧的API。 POSIX消息队列比System V消息队列提供了更好的设计接口。另一方面,POSIX消息队列(特别是在较旧的系统上)不如System V消息队列广泛可用。
Linux当前(2.6.26)不支持对POSIX消息队列使用访问控制列表(ACL)。
BUGS
在Linux版本3.5至3.14中,内核对可以将queues_max限制提高到的值施加上限1024(HARD_QUEUESMAX),并且即使对于特权进程也强制实施该上限。在Linux 3.14中,此上限值已删除,对稳定内核3.5.x至3.13.x的补丁程序也删除了该上限。
按照最初的实现方式(并记录在案),QSIZE字段显示消息队列中所有消息中(用户提供的)字节的总数。 Linux 3.5中的一些更改无意中改变了行为,因此该字段还包括用于将消息存储在队列中的内核开销字节数。这种行为回归已在Linux 4.2(及更早的稳定内核系列)中得到纠正,因此计数再次仅包含队列中消息中用户数据的字节数。
示例
mq_notify(3)中显示了使用各种消息队列功能的示例。
另外参见
getrlimit(2),mq_getsetattr(2),poll(2),select(2),mq_close(3),mq_getattr(3),mq_notify(3),mq_open(3),mq_receive(3),mq_send(3), mq_unlink(3),epoll(7),名称空间(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。