文章目录
- 概述
- 函数说明
- 创建/销毁
- mq_open
- mq_close
- mq_unlink
- 属性操作
- 类型定义
- mq_getattr
- mq_setattr
- 接收/发送
- 消息队列限制
- 参考链接
概述
消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据。
消息队列中的每条消息通常具有以下属性:
- 一个表示优先级的整数;
- 消息的数据部分的长度;
- 消息数据本身;
函数说明
头文件
#include <mqueue.h>
创建/销毁
mq_open
- 创建/打开消息队列
mqd_t mq_open(const char *name, int oflag, ...)
mqd_t mq_open(const char *name, int oflag, mode_t mode, mq_attr* attr) //O_CREAT
参数说明:
- name:表示消息队列的名字,name参数一定要以"/"字符开头,所有使用相同name值调用mq_open函数的线程,访问的都是同一个消息队列
- oflag:消息队列的访问方式
- mode:可选参数,在oflag中含有O_CREAT标志且消息队列不存在时,才需要提供该参数。表示默认访问权限
- attr:可选参数,在oflag中含有O_CREAT标志且消息队列不存在时才需要。该参数用于给新队列设定某些属性,如果是空指针,那么就采用默认属性。
关于oflag的取值说明:
必选参数
- O_RDONLY:只读模式,open返回的描述符可用来调用mq_receive(),但是不能用于函数 mq_send(),一个消息队列可以在相同或不同的进程中多次打开用来接收消息
- O_WRONLY:只写模式,open返回的描述符用于函数 mq_send(), 但是不能用于函数 mq_receive(),一个消息队列可以在相同或不同的进程中多次打开用来接收消息
- O_RDWR:读写模式,可以使用任何支持O_RDONLY 和O_WRONLY 访问模式的函数,一个消息队列可以在相同或不同的进程中多次打开用来发送消息
可选参数
- O_CREAT:
创建一个消息队列. 使用这个参数需要追加2个参数:mode和attr
如果name参数指定的消息队列已经存在, 那么这个参数将不起任何作用, 除非像下面 O_EXCL 中提到的情况;
如果name参数指定的消息队列不存在, 会创建一个空的消息队列。- O_EXCL:
如果 O_EXCL 和O_CREAT同时被设置了, 如果消息队列应经存在,那么函数 mq_open() 会返回失败.
该参数提供了检查消息队列是否存在的方法, 如果设置了 O_EXCL 必须同时设置 O_CREAT ,否则结果未定义.- O_NONBLOCK:
决定函数 mq_send() 和 mq_receive() 在获取当前无法获得的资源或消息时,是一直等待(阻塞), 还是返回失败并将 errno 设置成 [EAGAIN];返回值
- 成功:返回文件描述符
失败:-1,并给出errno
mq_close
- 关闭消息队列
int mq_close (mqd_t __mqdes)
说明:
- 和文件的close类型,关闭后,消息队列并不从系统中删除。一个进程结束,会自动调用关闭打开着的消息队列。
mq_unlink
- 销毁消息队列
mqd_t mq_unlink(const char *name);
- 消息队列创建后只有通过调用该函数或者是内核自举才能进行删除。
- 每个消息队列都有一个保存当前打开着描述符数的引用计数器,和文件一样,因此本函数能够实现类似于unlink函数删除一个文件的机制。
属性操作
类型定义
struct mq_attr
{
long int mq_flags; //消息队列的标志:0或O_NONBLOCK,用来表示是否阻塞
long int mq_maxmsg; //消息队列的最大消息数
long int mq_msgsize; //消息队列中每个消息的最大字节数
long int mq_curmsgs; //消息队列中当前的消息数目
long int __pad[4];
};
mq_getattr
- 获取队列属性
mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);
参数说明:
- mqdes:mqueue标识符;
- attr:获取的消息队列的属性
mq_setattr
- 设置队列属性
mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
参数说明:
- mqdes:mqueue标识符;
- newattr:设置的消息队列属性;
- oldattr:用于保存修改前的消息队列的属性,可以为空。
注意:
- mq_setattr可以设置的属性只有mq_flags,用来设置或清除消息队列的非阻塞标志。newattr结构的其他属性被忽略。
- mq_maxmsg和mq_msgsize只能在创建消息队列时通过mq_open来设置。mq_open只会设置该两个属性,忽略另外两个属性。
- mq_curmsgs属性只能被获取而不能被设置。
接收/发送
mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);
mqd_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);
#ifdef __USE_XOPEN2K
mqd_t mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
unsigned msg_prio, const struct timespec *abs_timeout);
mqd_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,
unsigned *msg_prio, const struct timespec *abs_timeout);
#endif
参数说明:
- mqdes:消息队列描述符;
- msg_ptr:指向消息体缓冲区的指针;
- msg_len:消息体的长度,
- 接收:该参数要大于等于mq_msgsize的,如果小于该值,就会返回EMSGSIZE错误;
- 发送:该长度可以为0。
- msg_prio:消息的优先级;
- 它是一个小于MQ_PRIO_MAX的数,数值越大,优先级越高。
- POSIX消息队列在调用mq_receive时总是返回队列中最高优先级的最早消息。
- 如果消息不需要设定优先级,那么可以在mq_send是置msg_prio为0,mq_receive的msg_prio置为NULL。
发送返回值:
- 成功:返回0;
- 失败:返回-1,并设置错误码
接收返回值:
- 成功:返回接收到消息的字节数;
- 失败:返回-1,并设置错误码
注意:
- 默认情况下mq_send和mq_receive是阻塞进行调用,可以通过mq_setattr来设置为O_NONBLOCK
消息队列限制
- 消息队列的限制主要指对mq_maxmsg和mq_msgsize的限制,这两个参数在调用mq_open创建一个消息队列的时候设定。当这个设定是受到系统内核限制的,下面是在Linux 2.6.18下shell对启动进程的POSIX消息队列大小的限制:
mq_maxmsg = 10
mq_msgsize = 8192
- POSIX消息队列在实现上还有另外两个限制:
**MQ_OPEN_MAX**:一个进程能同时打开的消息队列的最大数目,POSIX要求至少为8;
**MQ_PRIO_MAX**:消息的最大优先级,POSIX要求至少为32;