在某个进程往一个队列写入消息之前,并不需要另外有个进程在该队列上等待消息的到达,这跟管道和FIFO是相反的,对于后两者来说,除非读出者已存在,否则先有写入者是没有意义的
1、mq_open、mq_close和mq_unlink函数
mq_open函数创建一个新的消息队列或者打开一个已存在的消息队列
#include
mqd_t mq_open(const char *name, int oflags, .../*mode_t mode, struct mq_attr *attr*/);
成功返回消息队列描述字,失败返回-1
oflags参数是O_RDONLY、O_WRONLY、O_RDWR之一,可能按位或上O_CREAT、O_EXCL或O_NONBLOCK
当操作是创建一个队列时,mode和attr参数是需要的。attr参数用于给新队列指定某些属性,如果它为空指针,就使用默认属性
消息队列描述字与文件或套接口描述字是不一样的
已打开的消息队列用mq_close关闭
#include
int mq_close(mqd_t mqdes);
成功返回0,失败返回-1
要从系统中删除用作mq_open第一个参数的某个name,必须用mq_unlink
#include
int mq_unlink(const char *name);
成功返回0,失败返回-1
编译时注意:
(1)、添加目录,挂载消息队列虚拟文件系统
mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue
(2)、指定name时用这种形式/pathname
(3)、添加-lrt
2、mq_getattr和mq_setattr函数
每个消息队列有四个属性,mq_getattr返回所有的这些属性,mq_setattr则设置其中某个 属性
#include
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; //message queue flag:0, O_NONBLOCK
long mq_maxmsg; //队列中允许的最大的消息数目
long mq_msgsize;//单个消息的最大大小
long mq_curmsgs;//当前消息队列中的消息个数
};
指向某个mq_attr结构的指针可作为mq_open的第四个参数,从而允许在该函数的实际操作中创建一个消息队列,给它指定mq_maxmsg和mq_msgsize属性.mq_open忽略该结构的另个两个成员
mq_getattr把所指定队列的当前属性填入attr指向的结构
mq_setattr给指定的队列设置属性,只能设置mq_flags,每个队列的最大消息数和每个消息的最大字节数只能在创建时设置,当前消息数则只能获取不能设置
3、mq_send和mq_receive函数
每个消息有一个优先级,小于MQ_PRIO_MAX的无符号整数
mq_receive总是返回指定队列中的优先级最高的最早消息,而且该优先级能随该消息的内容及其长度返回
#include
int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio); 成功返回0,失败返回-1
int mq_receive(mqd_t mqdes, char *ptr, size_t lne, unsigned int *prio); 成功返回消息中的字节数,失败返回-1
4、消息队列的限制
有两个限制:
(1) MQ_OPEN_MAX:一个进程同时打开的消息队列的最大数目
(2)MQ_PRIO_MAX:任意消息的最大优先级值 加1
5、mq_notify函数
适用情况:往空队列中放置了一个消息
两种方式 :
(1)产生一个信号
(2)创建一个线程执行一个指定的函数
函数定义
#include
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
成功返回0,失败返回 -1
信号常值 都 定义在
union sigval
{
int sival_int;
void *sival_ptr;
};
struct sigevent
{
int sigev_notify;//通知类型,有SIGEV_(NONE, SIGNAL, THREAD)
int sigev_signo;//SIGEV_SIGNAL时的信号值
uniong sigval sigev_value;//传递给信号处理函数或者线程的值
void (*sigev_notify_function)(union sigval);
pthread_attr_t *sigev_notify_attributes;
};
函数的若干规则:
(1)notification非空,表示有一个消息到达该队列并且先前为空时得到通知
(2)notification为空,表示注册被撤销
(3)任意时刻只有一个进程可以注册为接收某个队列的通知
(4)当有一个消息到达先前为空的队列时,且有一个进程注册为接收该队列的通知时,只有没有任何线程阻塞在该队列的mq_receive调用的前提下,通知才会发出。即mq_receive调用 中的阻塞优先于任何通知的注册
(5)当通知发送给注册进程时,其注册被撤销,须再次调用 mq_notify注册