当前位置:文档之家› posix消息队列使用全面介绍

posix消息队列使用全面介绍

POSIX消息队列是linux进程间通信的重要方式,下面按照创建,使用,关闭的顺序讲述了POSIX消息队列的使用方法:创建POSIX消息队列:mq_open#include<mqueue.h>mqd_t mq_open(const char *name,int oflag,int mode,mq_addr *attr);参数说明:Name:消息队列的名字字符串,必须以’/’开头,否则会出错。

Oflag: 表示打开的方式,1.首先必须说明读写方式,可以使以下的值之一:O_RDONLY:建立的队列是只读的O_WRONLY:建立的队列是只写的O_RDWR:建立的队列是可读可写2.必须有O_CREATE,说明是创建消息队列。

3.还有可选的选项:O_NONBLOCK:说明在创建的队列上发送和接收消息时,如果没有资源,不会等待,之间返回,如果不设置这个选项,缺省是会等待。

O_EXCL:在创建队列时,检测要创建的队列的名字是否已经存在了,如果已存在,函数会返回出错可以以或的方式形成Oflag,例如:O_RDWR|O_CREAT|O_EXCL Mode:是一个可选参数,在oflag中含有O_CREA T标志且消息队列不存在时,才需要提供该参数。

表示默认的访问权限,这个权限和文件访问的权限是相同的,取值也相同。

Mode可以由多个值组合而成,如:S_IRUSR|S_IWUSR,队列的所有者有读和写的权限。

Attr:指向结构struct mq_attr的指针。

我们可以在创建队列时通过这个结构设置队列的最大消息数和每个消息的最大长度。

struct mq_attr{long mq_flags; // 0或者O_NONBLOCK,说明是否等待long mq_maxmsg; //队列中包含的消息数的最大限制数long mq_msgsize; //每个消息大小的最大限制数long mq_curmsgs; //当前队列中的消息数}mq_maxmsg和mq_msgsize属性只能在创建消息队列时通过mq_open来设置。

mq_open 只会设置该两个属性,忽略另外两个属性。

mq_curmsgs属性只能被获取而不能被设置。

当attr参数为NULL时则使用linux的默认值msg_max ,msgsize_max 。

而使用mq_open创建一个新的队列时,attr只能给它指定mq_maxmsg,mq_msgsize这两个属性。

mq_open忽略attr结构中的另外两个成员。

在创建过程中需要注意的是,指定的这两个属性都必须小于等于msg_max或者msgsize_max的。

查看系统中消息队列的这两个限制值的方法是:cat /proc/sys/fs/mqueue/msg_maxcat /proc/sys/fs/mqueue/msgsize_max系统默认值有些时候不够大,需要我们对这个限制数进行修改,方法如下:修改/etc/sysctl.conf 在这个文件中添加#mqueue max fs.mqueue.msg_max=100 fs.mqueue.msgsize_max=9000 fs.mqueue.queues_max=520 保存好后重启系统就好了。

返回值:函数的返回值是mqd_t类型,是消息队列的描述符。

这实际是一个整数。

当函数执行出错时,会返回-1.要注意的是,描述符对于不同的进程/线程是不一样的,因此不同的进程/线程不能使用其他进程/线程的描述符。

打开消息队列:当一个进程在使用消息队列发送和接收消息之前,必须先打开消息队列。

以获得专属于本进程的对于这个消息队列的描述符。

打开消息队列的函数和创建消息队列的函数是一样的,区别在于参数要少2个。

mqd_t mq_open(const char *name,int oflag,);参数:Name:消息队列的名字字符串,必须以’/’开头,否则会出错。

Oflag: 表示打开的方式,说明读写方式,可以使以下的值之一:O_RDONLY:建立的队列是只读的O_WRONLY:建立的队列是只写的O_RDWR:建立的队列是可读可写返回值:函数的返回值是mqd_t类型,是消息队列的描述符。

在发送和接收消息队列的函数中需要这个描述符来指定是哪个消息队列。

这个值实际是一个整数。

当函数执行出错时,会返回-1.要注意的是,描述符对于不同的进程/线程是不一样的,因此不同的进程/线程不能使用其他进程/线程的描述符。

获取消息队列的属性一个进程在发送和接收消息之前,需要了解消息对象的属性,如消息的最大长度。

以便设定接收和发送的buffer大小。

mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);参数:Mqdes:打开消息队列时获取的描述符。

Attr:指向结构struct mq_attr的指针,用来获取消息队列的四个属性struct mq_attr{long mq_flags; // 0或者O_NONBLOCKlong mq_maxmsg; //队列中包含的消息数的最大限制数long mq_msgsize; //每个消息大小的最大限制数long mq_curmsgs; //当前队列中的消息数}设置消息队列属性我们可以设置消息队列的属性,实际只能设置flag标志,说明队列中没有消息时,接收消息的进程是否在队列上继续等待。

mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);参数:Mqdes:打开消息队列时获取的描述符。

Attr:指向结构struct mq_attr的指针,用来获取消息队列的最大消息个数和最大消息长度。

放到数据结构的mq_maxmsg和mq_msgsize中。

struct mq_attr{long mq_flags; // 0或者O_NONBLOCK,只能设置这个long mq_maxmsg; //队列中包含的消息数的最大限制数long mq_msgsize; //每个消息大小的最大限制数long mq_curmsgs; //当前队列中的消息数}oldattr:用来保存设置之前的attr值,可以为NULL.发送消息进程在打开消息队列后,可以使用下面的函数发送消息#include <mqueue.h>int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio);参数:mqdes: 打开消息队列时获得的描述符。

ptr: 指向发送缓冲区的指针,发送缓冲区存放了要发送的数据。

Len: 要发送的数据的长度。

prio :消息的优先级;它是一个小于MQ_PRIO_MAX的数,数值越大,优先级越高。

POSIX消息队列在调用mq_receive时总是返回队列中最高优先级的最早消息。

如果消息不需要设定优先级,那么可以在mq_send是置prio为0,mq_receive的prio置为NULL。

返回值:发送成功,返回0,失败,返回-1.接收消息进程在打开消息队列后,可以使用下面的函数接收消息。

ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len, unsigned int *prio);参数:mqdes: 打开消息队列时获得的描述符。

ptr: 指向接收缓冲区的指针。

接收缓冲区用来存放收到的消息。

Len: 接收缓冲区的长度。

len不能小于mq_msgsize,否则会返回EMSGSIZEprio :消息的优先级;它是一个小于MQ_PRIO_MAX的数,数值越大,优先级越高。

POSIX消息队列在调用mq_receive时总是返回队列中最高优先级的最早消息。

如果消息不需要设定优先级,那么可以在mq_send是置prio为0,mq_receive的prio 置为NULL。

返回值:接收成功,返回0,失败,返回-1.消息队列的关闭mqd_t mq_close(mqd_t mqdes);关闭消息队列,但不能删除它成功返回0,失败返回-1删除消息队列mqd_t mq_unlink(const char *name);成功返回0,失败返回-1当某个进程还没有关闭此消息队列时,调用mq_unlink时,不会马上删除队列,当最后一个进程关闭队列时,该队列被删除例子:下面的例子给出了发送和接收进程中如何创建消息队列,获取消息队列属性,发送消息和接收消息发送进程:创建并发送消息。

#include <mqueue.h>#include <fcntl.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h> int main(int argc, char **argv){int flags = 0;mqd_t mqd;flags = O_RDWR | O_CREAT;char *mq_name = (char*)"/MQ_Msg";struct mq_attr attr;long int msgsize = 1024;long int maxmsg = 200;attr.mq_msgsize = msgsize;attr.mq_maxmsg = maxmsg;mqd = mq_open(mq_name, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &attr);if (mqd == -1){printf("mq create error\n");return 0;}printf("Create MQ success!\nMax msgs = %ld, Max bytes/msg = %ld\n", attr.mq_maxmsg, attr.mq_msgsize);char msg[1024] = "hello";unsigned int prio = 1;int i;for (i = 0; i < 100; i++){mq_send(mqd, msg, msgsize, prio);}mq_close(mqd);return 0;}接收进程:打开并接收消息#include <unistd.h>#include <fcntl.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h> int main(int argc, char **argv){mqd_t mqd;long n;int flags = 0;unsigned int prio = 0;char *buff;struct mq_attr attr;char *mq_name = (char*)"/MQ_Msg";flags = O_RDONLY;mqd = mq_open(mq_name, flags);if (mqd == -1){printf("mq open error\n");return 0;}mq_getattr(mqd, &attr);buff = (char*)malloc(attr.mq_msgsize);while ((n = mq_receive(mqd, buff, attr.mq_msgsize, &prio))){printf("read %ld bytes, msg is %s, priority = %u\n", n, buff, prio);}mq_close(mqd);return 0;}进阶话题:异步事件通知POSIX消息队列可以在空队列收到第一个消息时发送事件通知给需要的进程。

相关主题