POSIX消息队列与System V消息队列的主要区别:
1.对POSIX队列的读总数返回最高优先级到最早消息,对SV队列到读则可以返回任意指定优先级的消息
2.当往一个空队列放置一个消息时,POSIX允许产生一个信号或启动一个线程,System V不提供此机制
消息的属性:
1.一个无符号整数的优先级(POSIX)或一个长整数的类型(SV)
2.消息的数据部分长度(可以为0)
3.数据本身(如果长度大于0)
POSIX消息队列总结:
mq_open创建一个新队列或者打开一个已经存在的队列
mq_close关闭队列
mq_unlink删除队列名,删除队列
mq_send往队列放置消息
mq_receive从一个队列中读出消息
mq_setattr和mq_getattr查询和设置队列的属性
mq_notify允许注册一个信号或者线程,在有一个消息被放置到空队列时,发送信号或者激活线程
每个消息被赋予一个小整数优先级,mq_receive总是返回最高优先级的最早消息
限制:
/proc/sys/fs/mqueue/msg_max 10
/proc/sys/fs/mqueue/msgsize_max 8192
/proc/sys/fs/mqueue/queues_max 256
创建一个新的消息队列或者打开一个已经存在的消息队列
<mqueue.h> 注意:编译加-lrt
<fcntl.h>
<sys/stat.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);
成功返回描述字,失败返回-1并设置errno
name: 必须为/开头!!!
oflag: O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_NONBLOCK
关闭消息队列,但不能删除它
mqd_t mq_close(mqd_t mqdes);
成功返回0,失败返回-1
删除消息队列,不一定马上删除消息队列,但队列名会立即删除,(真正的析构发生在引用计数为0的时候)
mqd_t mq_unlink(const char *name);
成功返回0,失败返回-1
当某个进程还没有关闭此消息队列时,调用mq_unlink时,不会马上删除队列,当最后一个进程关闭队列时,该队列被删除
int flags;
mqd_t mqd;
flags = O_RDWR | O_CREAT | O_EXCL;
mqd = mq_open("/tmp.111", flags, 0644, NULL);
if (mqd == (mqd_t)-1) {
perror("mq_open");
return 1;
}
消息队列的属性
mq_getattr mq_setattr
mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);
mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
成功返回0,失败返回-1
收发消息
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
成功返回消息的长度,消息的实际长度,不包括消息头;失败返回-1
msg_len指示msg_ptr的长度,必须大于等于mq_msgsize
如果msg_prio不为NULL,函数返回消息的优先级
如果队列为空,调用将阻塞,如果队列设置0_NONBLOCK,调用立即返回EAGAIN
队列限制
long int open_max = sysconf(_SC_MQ_OPEN_MAX); // -1
long int prio_max = sysconf(_SC_MQ_PRIO_MAX); // 32768
消息通告
当往空队列放置了一个消息时,通知进程
通告方式有2种:
1. 产生一个信号
2. 创建一个线程执行一个指定的函数
mqd_t mq_notify(mqd_t mqdes, const struct sigevent *notification);
成功返回0;失败返回-1
给队列建立或者删除异步事件通知
1.如果notification非空,那么当前进程希望在有一个消息到达而且队列先前为空时得到通知,该进程被注册为接收该队列的通知
2.如果notification为空,而且当前进程目前被注册为接收该队列的通知,那么现有注册将被撤销
3.任意时刻只有一个进程可以被注册为接收队列的通知
4.当有一个消息到达一个空队列,而且已经有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用的前提下,通知才会发送。即在mq_receive调用中的阻塞比任何通知的注册都优先
5.当该通知已经发送给它的注册进程时,其注册即被撤销。该进程必须再次调用mq_notify以重新注册
1.对POSIX队列的读总数返回最高优先级到最早消息,对SV队列到读则可以返回任意指定优先级的消息
2.当往一个空队列放置一个消息时,POSIX允许产生一个信号或启动一个线程,System V不提供此机制
消息的属性:
1.一个无符号整数的优先级(POSIX)或一个长整数的类型(SV)
2.消息的数据部分长度(可以为0)
3.数据本身(如果长度大于0)
POSIX消息队列总结:
mq_open创建一个新队列或者打开一个已经存在的队列
mq_close关闭队列
mq_unlink删除队列名,删除队列
mq_send往队列放置消息
mq_receive从一个队列中读出消息
mq_setattr和mq_getattr查询和设置队列的属性
mq_notify允许注册一个信号或者线程,在有一个消息被放置到空队列时,发送信号或者激活线程
每个消息被赋予一个小整数优先级,mq_receive总是返回最高优先级的最早消息
限制:
/proc/sys/fs/mqueue/msg_max 10
/proc/sys/fs/mqueue/msgsize_max 8192
/proc/sys/fs/mqueue/queues_max 256
创建一个新的消息队列或者打开一个已经存在的消息队列
<mqueue.h> 注意:编译加-lrt
<fcntl.h>
<sys/stat.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);
成功返回描述字,失败返回-1并设置errno
name: 必须为/开头!!!
oflag: O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_NONBLOCK
关闭消息队列,但不能删除它
mqd_t mq_close(mqd_t mqdes);
成功返回0,失败返回-1
删除消息队列,不一定马上删除消息队列,但队列名会立即删除,(真正的析构发生在引用计数为0的时候)
mqd_t mq_unlink(const char *name);
成功返回0,失败返回-1
当某个进程还没有关闭此消息队列时,调用mq_unlink时,不会马上删除队列,当最后一个进程关闭队列时,该队列被删除
int flags;
mqd_t mqd;
flags = O_RDWR | O_CREAT | O_EXCL;
mqd = mq_open("/tmp.111", flags, 0644, NULL);
if (mqd == (mqd_t)-1) {
perror("mq_open");
return 1;
}
消息队列的属性
mq_getattr mq_setattr
mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);
mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
成功返回0,失败返回-1
收发消息
mq_send mq_receive
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
成功返回消息的长度,消息的实际长度,不包括消息头;失败返回-1
msg_len指示msg_ptr的长度,必须大于等于mq_msgsize
如果msg_prio不为NULL,函数返回消息的优先级
如果队列为空,调用将阻塞,如果队列设置0_NONBLOCK,调用立即返回EAGAIN
队列限制
long int open_max = sysconf(_SC_MQ_OPEN_MAX); // -1
long int prio_max = sysconf(_SC_MQ_PRIO_MAX); // 32768
消息通告
当往空队列放置了一个消息时,通知进程
通告方式有2种:
1. 产生一个信号
2. 创建一个线程执行一个指定的函数
mqd_t mq_notify(mqd_t mqdes, const struct sigevent *notification);
成功返回0;失败返回-1
给队列建立或者删除异步事件通知
1.如果notification非空,那么当前进程希望在有一个消息到达而且队列先前为空时得到通知,该进程被注册为接收该队列的通知
2.如果notification为空,而且当前进程目前被注册为接收该队列的通知,那么现有注册将被撤销
3.任意时刻只有一个进程可以被注册为接收队列的通知
4.当有一个消息到达一个空队列,而且已经有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用的前提下,通知才会发送。即在mq_receive调用中的阻塞比任何通知的注册都优先
5.当该通知已经发送给它的注册进程时,其注册即被撤销。该进程必须再次调用mq_notify以重新注册
6.当调用mq_notify但是队列不为空时,通知不会发送;当队列变为空,并且有一个消息入队时,才发送通知
下面是使用内存映射实现的消息队列,消息队列的数据结构如下:
<