5.1 概述
消息队列可认为是一个消息链表。有足够写权限的线程可往队列里放置消息,有足够读权限的线程可从队列里取走消息。
队列中每个消息都具有如下属性:
一个无符号整数优先级或一个长整数类型
消息的数据部分长度
数据本身
5.2 mq_open、mq_close和mq_link函数
Mq_open函数创建一个新的消息队列或打开一个已存在的消息队列
#include<mqueue.h>
mqd_t mq_open(const cahr *name, int flag, …)
//返回:成功时为消息队列描述字,出错时为-1
oflag参数是O_RDONLY,O_WRONLY或O_RDWR之一,可能按位或上O_CREAT,O_EXCL或O_NONBLOCK
已打开的消息队列是由mq_close关闭的
#include<mqueue.h>
Int mq_close(mqd_t mqdes);
//返回:成功时为0,出错时为-1
其功能只是关闭该消息队列,并不从系统中删除。只有当进程终止时才删除
要想删除mq_open的第一个参数name必须调用mq_link
#include<mqueue.h>
Int mq_unlink(const char *name);
//返回:成功时为0,出错时为-1
5.3 mq_getattr和mq_setattr函数
#include<mqueue.h>
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。
struct mq_attr结构如下:
struct mq_attr{
long mq_flags; /* Message queue flags:0,O_NONBLOCK */
long mq_maxmsg; /* Maximum number of messages. */
long mq_msgsize; /* Maximum message size. */
long mq_curmsgs; /* Number of messages currently queued. */
};
5.4 mq_send和mq_receive函数
#include<mqueue.h>
int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio);
//返回:成功时返回0,出错返回-1
ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len, unsigned int *proip);
//返回:成功为消息中的字节数,出错为-1
5.5 消息队列限制
我们已遇到任意给定队列的两个限制
mq_mqxmsg 队列中的最大消息数
mq_msgsize 任意消息的最大字节数
消息队列的实现定义了另外两个限制
MQ_OPEN_MAX 一个进程能够打开的最大进程数(至少为8)
MQ_PRIO_MAX 任意消息的最大优先值加1(至少为32)
5.6 mq_notify函数
Posix消息队列允许异步事件通知,以告知何时有一个消息放到了某个空消息队列中。这种通知有两种方式可供选择:
产生一个信号
创建一个线程执行一个指定函数
这种通知通过调用mq_notify建立
#include<mqueue.h>
int mq_notify(mqd_t mqdes, const struct sigevent *notification);
返回:成功时为0,出错时为-1
union sigval {
int sival_int;
void *sival_ptr;
}
struct sigevent {
union sigval sigev_value;
int sigev_signo;
int sigev_notify;
void (*sigev_notify_function)(union sigval);
pthread_attr_t *sigev_notify_attributes;
}
适用于该函数的规则:
如果notification参数非空,那么当前进程希望在有一个消息到达所指定的先前为空的队列时得到通知。我们说“该进程被注册为接收该队列的通知”。
如果notification参数为空指针,而且当前进程目前被注册为接收所指定队列的通知,那么已存在的注册将被撤销。
任意时刻只有一个进程可以被注册为接收某个指定队列的通知。
当有一个消息到达某个先前为空的队列,而且已有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用中的前提下,通知才会发出。这就是说,在mq_receive调用中的阻塞比任何通知的注册都优先。
当该通知被发送给它的注册进程时,其注册即被撤销。该进程必须再次调用mq_notify重新注册(如果想要的话)。
5.7 Posix实时信号
术语事实行为(realtime behaviour)隐含着如下特征
信号是排队的。
但有多种SIGRTMIN到SIGRTMAX范围内的解阻塞信号排队时,值较小的信号先于值较大的信号提交。
当某个非实时信号提交时,传递给它的信号处理程序的唯一参数是该信号的值。实时信号传递更多的信息。
一些新函数定义成使用实时信号工作