#include
#include
#include
mqd_t mq_open(const char*name ,int oflag,...
/*mode_t mode,struct mq_attr *attr);
POSIX IPC对象需要使用以斜线开头后面跟着一个或多个非斜线字符的名字
例如 /mq
oflag是位掩码
标记 | 描述 |
---|---|
O_CREAT | 不存在时创建 |
O_EXCL | 和O_CREAT一起排他创建 |
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 读写 |
O_NONBLOCK | 非阻塞 |
如果使用非阻塞方式打开,那么后续对此mqd_t的操作都会以非阻塞的方式进行
如果指定了O_CREATE,就需要mode 和attr参数(如果已经存在,则会忽略)
mode和open一样(0777…)
attr是mq_attr结构,指定了消息队列的特性。如果为NULL则会以默认特性创建。
fork()中子进程会接受父进程的消息队列描述符的副本,但是不会继承父进程的任何消息通知注册。
当一个进程执行了exec()或终止时,所有打开的描述符会被关闭。在相应队列上的通知注册也会注销
#include
int mq_close(mqd_t mqdes); 0 SECCESS -1 ERROR
关闭并不会删除。
#include
int mq_unlink(const char *name);0 SECCESS -1 ERROR
会将队列标记为在所有进程使用完该队列之后销毁该队列
struct mq_attr{
long mq_flags;//0或者O_NONBLOCK
long mq_maxmsg;
long mq_msgize;
long mq_curmsgs;//当前在队列中消息数量
}
在使用mq_open()创建消息队列时
mq_maxmsg字段定义了使用mq_send()向消息队列添加消息的数量上限 其值必须大于0
mq_msgsize字段定义了加入消息队列的每条消息的大小上限,值必须大于0
内核会根据这两个值来确定消息队列所需的最大内存量。创建后无法修改
#include
int mq_getattr(mqd_t mqdes,struct mq_attr *attr);
mq_flags其取值只有0_NONBLOCK。这个标记是根据mq_open的oflag来初始化的,可以修改
mq_curmsgs为当前位于队列中的消息数
#include
int mq_setattr(mqd_t mqdes,const struct mq_attr *newattr,struct mq_attr *oldattr);
唯一能修改的只有mq_flags
mq_getattr(mqd,&attr);
attr.mq_flags|=O_NONBLOCK;
mq_setattr(mqd,&attr,NULL);
#include
int mq_send(mqd_t mqdes,const char*msg_ptr,size_t msg_len,unisgned int msg_prio);
msg_len指定了消息的长度,其值必须小于mq_msgsize,否则会返回EMSGSIZE错误。(可以为0)
每条消息都用有一个非负整数的优先级,通过msg_prio参数指定,0为最低。
如果消息队列已满(到达了mq_maxmsg),那么后续的mq_send()调用会阻塞到队列中存在可用空间或者设置O_NONBLOCK之间调用失败并返回EAGIN错误。
#include
ssize_t mq_recive(mqd_t mqdes,char *msg_ptr,size_t msg_len,unsigned int *msg_prio);
将从mqdes引用的消息队列中删除一条优先级最高、存在时间最长的消息并将其放置在msg_ptr所指的缓冲区。msg_len表示缓冲区长度。不管消息多大,msg_len必须大于等于mq_msgsize。否则会调用失败并返回EMSGSIZE错误。
POSIX消息队列能够接受之前为空的队列上有可用消息的异步通知(队列从空变成非空)
#include
int mq_notify(mqd_t mqdes,const struct sigevent* notification);
注意:
在任何一个时刻都只能有一个进程向特定的进程注册通知。如果已经有进程注册,则会返回EBUSY错误
只有当一条新消息进入为空的队列,注册进程才会接到通知(0->1)
当向注册进程发送一个通知后就会删除注册信息
注册进程只有在当前不存在其他在该队列上调用mq_recive()而发生阻塞的进程时才会收到通知。如果其他进程在阻塞,那么该进程会读取消息,注册进程保持注册状态
一个进程可以通过调用mq_notify()时传入一个值为NULL的notification参数来撤销注册
union sigval{
int sival_int;
void *sival_ptr;
};
struct sigevent{
int sigev_notify;//方法
int sigev_signo;//
union sigval sigev_value;
void(*sigev_notify_function)(union sigval);
void *sigev_notify_attributes;
};
sigev_notify会被置为如下
SIGEV_NONE 不通知进程
SIGEV_SIGNAL
通过sigev_signo字段中指定的信号来通知进程。如果sigev_signo是一个实时信号,那么sigev_value字段将会指定信号外带数据。通过传入信号处理器的siginfo_t结构中的si_value字段或通过调用sigwaitinfo()返回值能够取得这部分数据。
SIGEV_THREAD
通过调用在sigev_notify_function中指定的函数来通知进程,就像在新的线程中启动该函数。sigev_notify_attributes字段可以为NULL或指向线程的特性pthread_attr_t结构的指针。sigev_value中指定的联合sigval值将会作为参数传入这个函数。
《Linux/Unix系统编程手册》