文章目录

  • 概述
  • 函数说明
  • 创建/销毁
  • 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个参数:modeattr
    如果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;