linux进程间通信之Posix消息队列
Posix消息队列与System V 消息队列的用法很相似,主要有以下区别:
1. 对Posix消息队列的读取总是返回最高优先级的最早消息,对System V 消息队列的读取可以返回指定优先级的消息。
2. Posix 消息队列允许产生一个信号或启动一个线程去向一个空队列写入一个消息,System V消息队列不可以。
Posix消息队列常用函数及头文件
#include <mqueue.h>
1. mqd_t mq_open(const char *name,int oflag,.../* mode_t mode, struct mq_attr *attr */);
返回值: 若成功则返回消息队列描述符,若出错返回-1
name: 为路径
oflag: 为O_RDONLY , o_WRONLY或O_RDWR之一,也可按位或上O_CREAT,O_EXCL,O_NONBLOCK.
当用O_CREAT表示去创建一个新消息队列且新消息队列不存在时,参数mode 和 attr 就需要了。
mode: 所属的用户权限
attr:用于给新队列指定某些属性,如果为空指针,即为默认属性。
mq_open 的返回值用于其他Posix消息队列函数的第一个参数
2. int mq_close(mqd_t mqdes);
返回值:成功返回0,出错返回-1
此函数功能是关闭该进程的该描述符指向的消息对列,但并不从系统中删除。
3. int mq_unlink(const char *name);
返回值:成功返回0,出错返回-1
此函数功能是删除系统中name指向的消息对列。
4. int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, const struct mq_attr *attr,struct mq_attr *oattr);
返回值:成功返回0,出错返回-1
mq_attr结构有以下属性:
struct mq_attr{
long mq_flags: //消息队列标志: 0,O_NONBLOCK
long mq_maxmsg; //消息队列中允许的最多消息条数
long mq_msgsize; //每条消息中的最大字节数
long mq_curmsgs; //消息队列中当前的消息数
};
mq_attr结构的指针可以作为mq_open的第四个参数传递(mq_attr *attr), 从而使当创建新的Posix消息队列时可以指定mq_maxmsg和mq_msgsize属性,其他两个成语属性被mq_open忽略。
mq_getattr: 获取消息队列当前属性并填入attr指向的结构。
mq_setattr: 设置指定消息队列的属性,但是只使用mq_flags成员,以设置或清除费阻塞标志。其他三个成员属性被忽略(mq_maxmsg和mq_msgsize只能创建时指定,mq_curmsgs只能获取不能设 置)。
5. int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio); 返回值:成功返回0,出错返回-1
ssize_t mq_recieve(mqd_t mqdes, char *ptr, size_t len, unsigned int *priop);
返回值:成功则返回消息中字节数,出错返回-1
mq_receive中的len参数的值不能小于mq_attr结构的mq_msgsize,否则,mq_receive立即返回EMSGSIZE错误。
mq_send中的prio参数是写入消息的优先级,必须小于MQ_PRIO_MAX。 如果mq_receive的priop是一个非空指针,则会存放返回消息的优先级。如果不使用优先级,可以mq_send时指定优先级为0, mq_receive时指定最后一个参数为空指针。
代码举例:
创建Posix消息对列mq_creat.c
- #include "stdio.h"
- #include "stdlib.h"
- #include "mqueue.h"
- int main(char argc,char **argv)
- {
- mqd_t mqdc;
- if(argc>1)
- {
- mqdc=mq_open(argv[1],O_CREAT|O_RDWR|O_WRONLY,0666,NULL);
- if(mqdc==-1)
- printf("open error\n");
- mq_close(mqdc);
- }
- return 0;
- }
Posix消息对列发送代码mq_send.c
- #include "stdlib.h"
- #include "stdio.h"
- #include "mqueue.h"
- int main(char argc,char **argv)
- {
- mqd_t mqds;
- void *ptr;
- size_t len;
- unsigned int prio;
- if(argc<3)
- printf("usage: ./send <name> <#bytes> <priority>\n");
- else
- {
- len=atoi(argv[2]);
- prio=atoi(argv[3]);
- mqds=mq_open(argv[1],O_WRONLY);
- if(mqds==-1)
- printf("open error\n");
- ptr=calloc(len,sizeof(char));
- mq_send(mqds,ptr,len,prio);
- mq_close(mqds);
- }
- return 0;
- }
Posix消息队列接收代码mq_receive.c
- #include "stdlib.h"
- #include "stdio.h"
- #include "mqueue.h"
- int main(char argc,char **argv)
- {
- mqd_t mqdr;
- ssize_t n;
- unsigned int prio;
- void *buff;
- struct mq_attr attr;
- if(argc>1)
- {
- mqdr=mq_open(argv[1],O_RDONLY);
- if(mqdr==-1)
- printf("open error\n");
- mq_getattr(mqdr,&attr);
- buff = malloc(attr.mq_msgsize);
- while((n=mq_receive(mqdr,buff,attr.mq_msgsize,&prio))<=0)
- {
- printf("wait\n");
- sleep(1);
- }
- printf("buff is %s,n=%d,prio=%d\n",buff,n,prio);
- mq_close(mqdr);
- }
- return 0;
- }
运行结果:
首先运行creat 创建新的消息队列: $ ./creat /mq_test
然后运行send 发送消息:
$ ./send /mq_test 20 2
$ ./send /mq_test 80 8
$ ./send /mq_test 40 4
$ ./send /mq_test 60 6
最后运行receive接收消息:
$ ./receive /mq_test
buff is ,n=80,prio=8
$ ./receive /mq_test
buff is ,n=60,prio=6
$ ./receive /mq_test
buff is ,n=40,prio=4
$ ./receive /mq_test
buff is ,n=20,prio=2
从运行结果来看,发送消息程序依次发送了优先级为2,8,4,6长度为20,80,40,60四个消息; 然后运行接收程序后首先接收到的是优先级最高为8,长度为80的消息,按优先级由高到低依次接收。
因为发送的数据是calloc出来的随机数据,打印结果无法显示,只能显示“buff is ”.
6. int mq_notify(mqd_t mqdes, const struct sigevent *notification); 返回值: 成功返回0,出错返回-1 此函数为指定Posix消息队列建立或删除异步事件通知。 注意点: 1)任意时刻只能一个进程注册接收某个消息队列通知。 2)通知接收到后,已存在的注册即被撤销,如果需要再次接收,需要再次注册。 3) 进程mq_receive的阻塞优先级大于注册接收通知的优先级。 |