第5章 Posix 消息队列
5.1 概述
消息队列可以认为是一个链表。有写权限的线程可往消息队列中放置消息,有读权限的线程可以从消息队列中取走消息。
消息队列和管道/FIFO的区别:
(1)消息队列往一个队列中写消息前,并不需要有一个进程/线程在等待消息的到达,管道/FIFO需要。
(2)Posix消息队列是随内核的持续性,管道/FIFO是随进程的。
Posix消息队列和System V消息队列的区别:
(1)Posix消息队列的读总是返回最高优先级(类型)的最早消息;System V消息队列的读可以返回指定优先级(类型)的消息;
(2)Posix消息队列可以产生一个信号,System V消息队列不可以。
5.2 函数
5.2.1 mq_open函数
| 头文件 | #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); | |
| 返回值 | 成功返回消息队列的描述符,失败返回-1 |
| name:只能以/开头,且之后不能有/ | |
| 参数 | oflag:O_RDONLY、O_WRONLY、O_RDWR、O_CREAT、O_EXCL、O_NOBLOCK |
| mode:0666 | |
| 说明 | 1.有2个函数的原因和open函数一样,参数中有...可变参数 |
| 2.第4个参数,有的版本传变量的地址,有的版本传变量 |
5.2.2 mq_close函数
| 头文件 | #include <mqueue.h> |
| 函数原型 | int mq_close(mqd_t mqdes); |
| 返回值 | 成功返回0,失败返回-1 |
| 说明 | 只是关闭消息队列描述符,但消息队列还在系统中 |
5.2.3 mq_unlink 函数
| 头文件 | #include <mqueue.h> |
| 函数原型 | int mq_unlink(const char *name); |
| 返回值 | 成功返回0,失败返回-1 |
| 说明 | 删除消息队列 |
注意:
1.编译时需要加上 -lrt
2.程序编译完成后,如果直接运行程序则提示mq_open失败,提示mq_open permission denied。解决办法是:
mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue
5.2.4 mqcreat 程序
#include <stdio.h>
#include <unistd.h>
#include <mqueue.h>
// mqcreat -e /mqueue
int main(int argc, char **argv)
{
;
int flags = O_RDWR | O_CREAT;
mqd_t mqd = ;
)
{
switch (c)
{
case 'e':
flags |= O_EXCL;
break;
default:
break;
}
}
)
{
printf("usage: mqcreate [-e] <name>\n");
;
}
// 打开或创建一个消息队列
mqd = mq_open(argv[optind], flags, , );
)
{
perror("mq_open error");
;
}
// 关闭消息队列
mq_close(mqd);
// 删除消息队列
//mq_unlink(argv[optind]);
;
}
5.3 消息队列的属性
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 */
};
每个消息队列有4个属性:是否阻塞、允许最大的消息数量、允许最大的字节、当前消息数量。
1.如果创建一个新队列,指定了mq_maxmsg、mq_msgsize则忽略其他两个成员。
2.如果设置成非阻塞的,则另外三个参数被忽略。
| 头文件 | #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 |
5.3.1 带属性的mq_creat程序
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <mqueue.h>
// mqcreat -e -m 1024 -z 8192 /mqueue
int main(int argc, char **argv)
{
;
int flags = O_RDWR | O_CREAT;
mqd_t mqd = ;
struct mq_attr attr;
memset(&attr, , sizeof(attr));
)
{
switch (c)
{
case 'e':
flags |= O_EXCL;
break;
case 'm':
attr.mq_maxmsg = atol(optarg);
break;
case 'z':
attr.mq_msgsize = atol(optarg);
break;
default:
break;
}
}
)
{
printf("usage: mqcreate [-e] <name>\n");
;
}
// 打开或创建一个消息队列
mqd = mq_open(argv[optind], flags, , attr);
)
{
perror("mq_open error");
;
}
// 关闭消息队列
mq_close(mqd);
// 删除消息队列
mq_unlink(argv[optind]);
;
}
5.4 mq_send 和 mq_receive 函数
mq_send是往消息队列中放消息;mq_receive从消息队列中取消息。每个消息都有一个优先级(类型),它是一个小于MQ_PRIO_MAX的无符号整数,Posxi的上限是32。
mq_receive总是返回队列中在最高优先级的最早消息。而System V的msgrcv函数可以返回指定优先级的最早消息。
| 头文件 | #include <mqueue.h> |
| 函数原型 | int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio); |
| 返回值 | 成功返回0,失败返回-1 |
| 函数原型 | ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio); |
| 返回值 | 成功返回字节数,失败返回-1 |
| 说明 | 1.mq_receive的len参数不能小于消息的最大值(mq_attr结构中mq_msgsize成员),如果小于就立即返回EMSGSIZE错误 |
| 2.mq_send的prio参数是待发消息的优先级(类型),其值必须小于32位无符号整数 | |
| 3.mq_receive的prio参数如果非空,所返回消息的优先级(类型)就放在这个地址中 | |
| 4.如果不需要指定优先级,则mq_send的prio参数为0,mq_receive的prio参数为NULL |
5.4.1 mqsend程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mqueue.h>
// mqsend /mqueue 100 1
int main(int argc, char **argv)
{
;
int flags = O_RDWR | O_CREAT;
mqd_t mqd = ;
struct mq_attr attr;
memset(&attr, , sizeof(attr));
)
{
printf("usage: mqsend <name> <bytes> <priority>\n");
;
}
// 打开或创建一个消息队列
mqd = mq_open(argv[], flags, , NULL);
)
{
perror("mq_open error");
;
}
unsigned ]);
unsigned ]);
, len);
int ret = mq_send(mqd, ptr, len, prio);
)
{
perror("mq_send error");
;
}
// 关闭消息队列
mq_close(mqd);
;
}
5.4.2 mqreceive程序
命令行选项-n指定非阻塞模式,这样消息队列中没有消息,mq_receive就返回一个错误。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mqueue.h>
// mqreceive [-n] /mqueue
int main(int argc, char **argv)
{
;
int flag = O_RDWR | O_CREAT;
mqd_t mqd = ;
struct mq_attr attr;
unsigned ;
)
{
switch (c)
{
case 'n':
flag |= O_NONBLOCK;
break;
default:
break;
}
}
)
{
printf("usage: mareceive [-n] <name>\n");
;
}
// 打开消息队列
mqd = mq_open(argv[optind], flag, , );
)
{
perror("mq_open error");
;
}
// 获取消息队列中消息的最大字节数
mq_getattr(mqd, &attr);
);
int n = mq_receive(mqd, buff, attr.mq_msgsize, &prio);
printf("read %d bytes, prio:%d\n", n, prio);
;
}
5.5 消息队列限制
mq_maxmsg 队列中的最大消息数,没有限制
mq_msgsize 消息的最大字节数,没有限制
MQ_OPEN_MAX 一个进程能同时打开消息队列的最大数目,有限制,查询方法是:sysconf(_SC_MQ_OPEN_MAX);
MQ_PRIO_MAX 消息的优先级要小于这个值,有限制,查询方法是:sysconf(_SC_MQ_PRIO_MAX);
5.5.1 mqsysconf 程序
第5章 Posix 消息队列的更多相关文章
- 第三十四章 POSIX消息队列
POSIX消息队列相关函数 mq_open 功能: 用来创建和访问一个消息队列 原型: mqd_t mq_open(const char *name, int oflag); //只能用来打开消息队列 ...
- Linux IPC POSIX 消息队列
模型: #include<mqueue.h> #include <sys/stat.h> #include <fcntl.h> mq_open() //创建/获取消 ...
- Posix消息队列
转载于:http://blog.csdn.net/zx714311728/article/details/53197196 1.消息队列 消息队列可以认为是一个消息链表,消息队列是随内核持续的.队列中 ...
- posix 消息队列
注意 在涉及到posix消息的函数时, gcc 编译时要加-lrt参数, 如 gcc -lrt unpipc.c mqpack.c send.c -o send gcc -lrt unpipc.c m ...
- Posix消息队列实现机制
本文是对<Unix 网络编程 卷2:进程通信>的笔记. 引言 消息队列是进程间通信的一种方式,可是如果不理解他的实现原理,会有众多不理解之处,下面就结合本书中的例子,对posix消息队列来 ...
- POSIX 消息队列相关问题
一.查看和删除消息队列要想看到创建的posix消息队列,需要在root用户下执行以下操作:# mkdir /dev/mqueue# mount -t mqueue none /dev/mqueue删除 ...
- Linux IPC实践(7) --Posix消息队列
1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For m ...
- 进程间通信--POSIX消息队列
相关函数: mqd_t mq_open(const char *name, int oflag); mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, si ...
- POSIX 消息队列 之 概述 链接方式
NAMEmq_overview —— POSIX消息队列概述 DESCRIPTIONPOSIX消息队列允许进程以消息的形式交换数据.此API与System V消息队列(msgget(2),msgsnd ...
随机推荐
- sublime安装sftp和ctags插件
1. 安装Package Control插件 , 安装是通过Sublime Text 2控制台.这是通过按Ctrl + `快捷访问.一旦打开,粘贴以下命令到控制台. 输入以下python代码 subl ...
- 木匠ing[索引]
古人有云,一个不会写代码的木匠不会是个好厨子. 为了响应这个号召,开始我的木工之路. 首先介绍一个网站,www.zuojiaju.com 木工爱好者 ,里面有大量的关于木匠的帖子,感谢一下. 以前只是 ...
- 【性能诊断】八、并发场景的性能分析(windbg案例,连接泄露)
此前遇到一个项目反馈系统宕机问题,摘要描述如下: 系统不定期出现卡死现象,在多个模块不同功能上都出现过,未发现与特定功能相关的明显规律: 当系统出现卡死现象时,新的用户无法登陆系统: 跟踪应用服务器, ...
- phpcmsv9如何实现添加栏目时不在首页内容区显示只在导航栏显示
之前王晟璟一直使用PHPCMSV9系统建过自己的个人门户网站,同时也建立了一个其他类型的网站,感觉非常不错,我不得不说PHPCMSV9的功能非常齐全,非常强大. 但有一点时常让王晟璟感到很烦脑,那就是 ...
- openstack(liberty):部署实验平台(二,简单版本软件安装 part1)
软件安装过程中,考虑到现在是一个实验环境,且也考虑到规模不大,还有,网络压力不会大,出于简单考虑,将各个节点的拓扑结构改了一下,主要体现在网络节点和控制节点并在了一起.在一个服务器上安装! 到目前位置 ...
- 如何利用gatling创建一个性能测试例
[原创博文,转载请声明出处] 基于上一篇博文介绍如何源码编译创建自己的gatling可执行工具,今天介绍一下如何基于gatling做性能测试! 由于gatling的测试例脚本是基于scala写的,所以 ...
- Android开发——通过扫描二维码,打开或者下载Android应用
Android开发——通过扫描二维码,打开或者下载Android应用 在实现这个功能的时候,被不同的浏览器折磨的胃疼,最后实现了勉强能用,也查考了一下其他人的博客 android实现通过浏览器点击 ...
- android下asynchttp库对于session的支持
默认asynchttp库不支持session,需要用户配置下cookie来处理,直接贴支持session的代码 package example.com.sessiontest; import andr ...
- item31,连续子数组的最大和
整型数组,元素有正数和负数.数组中一个或连续的多个整数组成一个子数组,求所有子数组中最大值. =========== 动态规划, 状态转移方程,max[].size = nums.size() max ...
- android中的数据库操作
如何在android中调用数据库资源 在android中主要有两种方法来实现对数据库的访问,一种是adb shell方式,另一种是通过相关的android 的java类来间接的对数据库来进行操作.其中 ...