消息队列可以当做一个消息链表,不同于FIFO和管道,某个进程往一个消息队列写入消息之前,不需要另外进程在该队列上等待消息的到达。
对posix消息队列的读总是返回最高优先级的最早消息。
常用函数:
创建或者打开一个消息队列:
#include <fcntl.h> /* For O_* constants */#include <sys/stat.h> /* For mode constants */
#include <mqueue.h>
mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode,
struct mq_attr *attr);
关闭消息队列:
#include <mqueue.h>
int mq_close(mqd_t mqdes);
删除消息队列:
posix消息队列具备随内核的持续性,就是说即使当前没有进程打开某个消息队列,该队列上的消息也将一直存在。
#include <mqueue.h>int mq_unlink(const char *name);
要真正的删除一个消息队列得这样:调用mq_unlink并让它的引用计数(close一次减少1)达到0。
获取消息队列属性:
#include <mqueue.h>
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, struct mq_attr *newattr,
struct mq_attr *oldattr);
其中消息队列属性结构体如下:
struct mq_attr {
long mq_flags; /* Flags: 0 or O_NONBLOCK */
long mq_maxmsg; /* Max. # of messages on queue */
long mq_msgsize; /* Max. message size (bytes) */
long mq_curmsgs; /* # of messages currently in queue */
};
接收和发送消息:
#include <mqueue.h>
int mq_send(mqd_t mqdes, const char *msg_ptr,
size_t msg_len, unsigned msg_prio);
#include <mqueue.h>
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
size_t msg_len, unsigned *msg_prio);
消息队列限制:
总共有四个限制,分别为:
mq_mqxmsg;mq_msgsize;
MQ_OPEN_MAX;MQ_PRIO_MAX:这两个是在<unistd.h>头文件里定义的,可以用sysconf获取。
例子:创建消息队列
代码:
//mqcreate.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <fcntl.h>
#include <sys/stat.h>
#define FILEMODE (S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP)
struct mq_attr attr;//消息队列属性结构体
int main(int argc, char **argv)
{
int c, flags;
mqd_t mqd;
flags = O_RDWR | O_CREAT;
while((c = getopt(argc, argv, "em:z:")) != -1) {//处理参数,带冒号的表示后面有参数的
switch(c) {
case 'e':
flags |= O_EXCL;
printf("the optind is :%d\n",optind);
break;
case 'm':
attr.mq_maxmsg = atol(optarg);
printf("the optind is :%d\n",optind);
break;
case 'z':
attr.mq_msgsize = atol(optarg);
printf("the optind is :%d\n",optind);
break;
}
}
if (optind != argc - 1) {
printf("usage: mqcreate [-e] [-m maxmsg -z msgsize] <name>");
exit(0);
}
if ((attr.mq_maxmsg != 0 && attr.mq_msgsize == 0) || (attr.mq_maxmsg == 0 && attr.mq_msgsize !=0)){
printf("must specify both -m maxmsg and -z msgsize");
exit(0);
}
mqd = mq_open(argv[optind], flags, FILEMODE, (attr.mq_maxmsg != 0) ? &attr : NULL);
mq_close(mqd);
exit(0);
}
例子:发送消息
代码:
//mqsend.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
int main(int argc, char **argv)
{
mqd_t mqd;
void *ptr;
size_t len;
unsigned int prio;
if (argc != 4) {
printf("usage: mqsend <name> <#bytes> <priority>");
exit(0);
}
len = atoi(argv[2]);
prio = atoi(argv[3]);
if ((mqd = mq_open(argv[1], O_WRONLY)) == -1){
printf("open error");
exit(0);
}
ptr = calloc(len, sizeof(char));
mq_send(mqd, ptr, len, prio);
exit(0);
}
例子:读取一个消息
代码:
//mqrecieve.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
int main(int argc, char **argv)
{
int c, flags;
mqd_t mqd;
ssize_t n;
unsigned int prio;
void *buff;
struct mq_attr attr;
flags = O_RDONLY;
while((c = getopt(argc, argv, "n")) != -1){
switch(c) {
case 'n':
flags |= O_NONBLOCK;
break;
}
}
if (optind != argc-1) {
printf("usage: mqreceive [-n] <name>");
exit(0);
}
mqd = mq_open(argv[optind], flags);
mq_getattr(mqd, &attr);
buff = malloc(attr.mq_msgsize);
n = mq_receive(mqd, buff, attr.mq_msgsize, &prio);
printf("read %ld bytes, priority = %u\n",(long) n,prio);
exit(0);
}