linux进程间通信:POSIX 消息队列
文章目录
- 基本介绍
- 相关编程接口
- 编程实例
- 消息队列通信实例
- 消息队列属性设置实例
基本介绍
关于消息队列的基本介绍,前面在学习system V的消息队列时已经有过了解,linux进程间通信:system V消息队列
- 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用链表方式进行消息管理。
- 进程之间的通信角色为:发送者和接受者
发送者:
a. 获取消息队列的ID(key或者msgid)
b. 将数据放入一个带有标识的消息结构体,发送到消息队列
接受者:
a. 获取消息队列的ID
b. 指定标识的消息从消息队列中读出,然后进一步后续处理 - 支持不同的进程标记不同的消息优先级(0,1,2…),并由内核态维护对应消息类型的链表。
- 内核态的0号消息类型维护了一个链表,用来保存按照时间顺序加入的消息
相关编程接口
mq_open
:创建或打开一个消息队列mq_send
:向消息队列写入一条消息mq_receive
:从消息队列中读取一条消息mq_close
:关闭进程打开的消息队列mq_unlink
:删除一个消息队列mq_setattr
:设置消息队列的一些额外属性mq_getattr
:获取消息队列的一些额外属性mq_notify
:异步通知
创建或打开一个消息队列
a. 头文件<mqueue.h> <sys/stat.h> <fcntl.h>
b. 函数使用:
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);
c. 函数功能:创建一个新的POSIX消息队列或者打开一个已存在的消息队列。且消息队列是由name标识
d. 函数参数:name
用来标识需要创建或者打开的ipc对象oflag
O_CREAT/O_RDONLY/O_WRONLY/O_RDWR/O_EXCL/O_NOBLOCK
标记使用什么样的方式打开ipc对象mode
位掩码,用来设置权限 8进制attr
设置消息队列的属性,若为NULL,使用默认属性,linux 3.5以后版本也可以通过/proc查看设置
主要数据结构如下:struct mq_attr {long mq_flags; /* Flags (ignored for mq_open()) */long mq_maxmsg; /* Max. # of messages on queue */long mq_msgsize; /* Max. message size (bytes) */long mq_curmsgs; /* # of messages currently in queue(ignored for mq_open()) */ };
e. 函数返回值
成功:返回消息队列对象的描述符
失败:返回-1,并设置errno关闭一个消息队列
a. 头文件 :#include <mqueue.h>
b. 函数使用:int mq_close(mqd_t mqdes);
c. 函数功能:关闭一个描述符为mqdes的消息队列
d. 返回值:
成功:返回0
失败:返回-1
e. 注意:POSIX消息队列在进程终止或者执行execve()时会自动关闭删除消息队列
a. 头文件:#include <mqueue.h>
b. 函数使用:int mq_unlink(const char *name);
c. 函数功能:删除通过name标识的消息队列;在所有进程使用完该队列之后销毁该队列;若打开该队列的所有进程都已关闭,则立即删除
d. 返回值:
成功:0
失败:-1向消息队列中写入消息
a. 头文件:#include <mqueue.h>
b. 函数使用:int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
c. 函数功能:将msg_ptr所指向的缓冲区中的消息内容添加到描述符mqdes所引用的消息队列中
d. 函数参数:mqdes
:消息队列描述符msg_ptr
: 指向存放消息的缓冲区指针msg_len
: 消息的长度[10,8192]msg_prio
: 消息队列中按优先级排序,设置为0标识无需优先级;该参数为POSIX消息队列和system V消息队列的差异,即POSIX是通过优先级来区分消息,system V是通过消息类型来区分消息
e. 返回值
成功:0
失败:-1从消息队列中接收数据
a. 头文件:#include <mqueue.h>
b. 函数使用:ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
c. 函数功能:默认从mqdes引用的消息队列中删除一条优先级最高、存放时间最长的消息;并将删除的消息保存在msg_ptr;
这里如果接收时指定优先级,可以读取指定优先级的消息,并存放在msg_ptr
d. 函数参数:mqdes
:消息队列描述符msg_ptr
: 指向存放消息的缓冲区指针msg_len
: 消息的长度[10,8192]msg_prio
: 消息队列中按优先级排序,设置为0标识无需优先级;
e. 返回值
成功:消息接收的字节数
失败:-1获取/设置消息队列的属性信息
a. 头文件#include <mqueue.h>
b. 函数使用:
int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, const struct mq_attr *newattr, struct mq_attr *oldattr);
c. 函数功能:获取或者修改一个由mqdes标识的消息队列的属性信息
d. 函数参数:mqdes
消息队列的唯一标识newattr
设置修改后的mq_attr结构体类型的属性信息oldattr
修改前的属性信息,如果当前参数为NULL,则默认设置从mq_getattr中获取到的属性信息
关于消息队列的属性设置如下两种方式:
- 通过proc文件系统
echo num > /proc/sys/fs/mqueue/queues_max
echo num > /proc/sys/fs/mqueue/msg_max
echo num > /proc/sys/fs/mqueue/msgsize_max
- 通过POSIX系统调用接口设置
mq_setattr
仅能设置mq_flags
mq_open
仅设置mq_maxmsg
和mq_msgsize
编程实例
最终创建的POSIX消息队列的实例存放在/dev/mqueue
路径下
消息队列通信实例
mq_demo.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>#include <mqueue.h>int main()
{mqd_t mq_id;//创建一个消息队列if ((mq_id = mq_open("/posix_msgqueue",O_RDWR | O_CREAT, 0666, NULL)) == -1) {printf("mq_open failed \n");_exit(-1);}struct mq_attr mq;//获取消息队列的各个属性if (mq_getattr(mq_id ,&mq) == -1 ){_exit(-1);}printf("mq_flags %ld\n",mq.mq_flags); //mq_open默认将当前属性忽略,则一般为0printf("mq_maxmsg %ld\n",mq.mq_maxmsg); //消息队列可以接收的最大消息容量为10个,当达到10个,则当前进程阻塞printf("mq_msgsize %ld\n",mq.mq_msgsize); //每个消最大容量printf("mq_curmsgs %ld\n",mq.mq_curmsgs);int ret;if ((ret = fork()) == -1) {printf("fork failed \n");_exit(-1);}//创建子进程用来接收消息队列的信息,且接收的优先级为NULL,即默认接收优先级最高且存放时间最长的消息else if (ret == 0 ) {char msg_buf[mq.mq_msgsize];memset (msg_buf , 0 , mq.mq_msgsize);while(1) {if (mq_receive(mq_id,msg_buf,mq.mq_msgsize,NULL) == -1) {printf("mq_receive failed \n");_exit(-1);}printf("child process receive msg :%s \n",msg_buf);sleep(1);}}else {while(1) {//父进程用来发送消息队列的信息,并设置发送的消息优先级为1//如果父进程发送多个优先级消息,子进程指定具体的一个优先级消息进行接收即可if (mq_send(mq_id,"hello world",sizeof("hello world"),1) == -1) {printf("mq_send failed\n");_exit(-1);}printf("parent process :send msg to mqueue success\n");sleep(1);}}//关闭当前进程对消息队列 mq_id的引用mq_close(mq_id);sleep(5);//引用计数为0时,删除当前进程创建的消息队列if(mq_unlink("/posix_msgqueue") == -1) {printf("mq_unlink failed\n");_exit(-1);}return 0;
}
输出如下:
消息队列属性设置实例
我们知道如下三个参数,POSIX消息队列默认的属性值为
mq_flags = 0
mq_maxmsg = 10
mq_msgsize = 8192
通过如下代码可以分别看到mq_open
和mq_setattr
对属性值的设置
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <string.h>int main () {mqd_t mq_id;/*使用mq_open同时对三个参数更改*/struct mq_attr addr;addr.mq_flags = O_NONBLOCK;addr.mq_maxmsg = 5;addr.mq_msgsize = 4096;//将需要设置对属性参数设置为addrmq_id = mq_open("/notify",O_WRONLY | O_CREAT, 0666, &addr);if (mq_id == -1) {printf("mq_open failed\n"); _exit(-1);}if (mq_getattr(mq_id,&addr) == -1) {printf("mq_getattr failed\n");_exit(-1);}//打印最终对设置结果printf("mq_open set mq_flags = %ld\n",addr.mq_flags);printf("mq_open set mq_maxmsg = %ld\n", addr.mq_maxmsg);printf("mq_open set mq_msgsize = %ld\n", addr.mq_msgsize);/*同样对所有的属性参数,使用mq_setattr进行设置*/struct mq_attr attr;attr.mq_flags = O_NONBLOCK;attr.mq_maxmsg = 8;attr.mq_msgsize = 2048;if(mq_setattr(mq_id,&attr,NULL) == -1) {printf("mq_set attr failed \n");_exit(-1);}if (mq_getattr(mq_id,&attr) == -1) {printf("mq_getattr failed\n");_exit(-1);}printf("mq_setattr set mq_flags = %ld\n",attr.mq_flags);printf("mq_setattr set mq_maxmsg = %ld\n", attr.mq_maxmsg);printf("mq_setattr set mq_msgsize = %ld\n", attr.mq_msgsize);return 0;
}
输出结果如下:
mq_open set mq_flags = 0
mq_open set mq_maxmsg = 5
mq_open set mq_msgsize = 4096
mq_setattr set mq_flags = 2048
mq_setattr set mq_maxmsg = 5
mq_setattr set mq_msgsize = 4096
可见,mq_flags参数只有mq_setattr系统调用能够成功设置
mq_maxmsg和mq_msgsize对属性仅能由mq_opn系统调用设置成功
相关文章:
opencv 修改图像数值_opencv 修改图像数值_Python中使用OpenCV读取像素
如何在Python中遍历像素呢?请看代码:import numpy as npimport cv2import matplotlib.pyplot as pltsrc cv2.imread("src.png")gray cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)rows, cols gray.shape[:2]row gray[200]plt.plot(row)# plt.sho…
SQL中返回一个字符串在另一个中存在的次数
ALTER FUNCTION [reg].[f_GetSameStringCntNoSort] ( str1 VARCHAR(100),--源字符串,取该串中的strLen长度的字符是否在目的字符串 str2 VARCHAR(100) --目的字符串 ) RETURNS INT AS BEGIN -- 返回的长度 DECLARE count INT DECLARE returnValue …
自由软件的自由
我相信我的订阅者中有很多是IT从业人员,我们在工作中会使用各种软件,除了微软、苹果等软件巨头的商业软件,还有更多的自由软件。我们使用这些软件构建自己的工作环境,为公司开发运营系统,为客户实现业务流程࿰…
c/c++ 拷贝控制 构造函数的问题
拷贝控制 构造函数的问题 问题1:下面①处的代码注释掉后,就编译不过,为什么??? 问题2:但是把②处的也注释掉后,编译就过了,为什么??? …
linux进程间通信:POSIX 消息队列 ----异步通信
在上一篇中linux进程间通信:POSIX 消息队列我们知道消息队列中在消息个数达到了队列所能承载的上限,就会发生消息的写阻塞。 阻塞式的通信影响系统效率,进程之间在通信收到阻塞时并不能去做其他事情,而是一直处于阻塞状态。 为了…
【转】Android设计中的.9.png
来源:http://isux.tencent.com/android-ui-9-png.html Android设计中的.9.png 注意:当使用9.png做TextView背景时,一定要设置内容区域(底部和右侧),否则,文字显示不出来。 偶米伽 2013.08.20在A…
python创建scrapy_Python爬虫教程-31-创建 Scrapy 爬虫框架项目
首先说一下,本篇是在 Anaconda 环境下,所以如果没有安装 Anaconda 请先到官网下载安装Scrapy 爬虫框架项目的创建0.打开【cmd】1.进入你要使用的 Anaconda 环境1.环境名可以在【Pycharm】的【Settings】下【Project:】下找到2.使用命令&#…
KOAProgressBar
2019独角兽企业重金招聘Python工程师标准>>> KOAProgressBar 是 iOS 上的一个进度条控件,要求 iOS 5 支持 转载:http://www.adobex.com/ios/source/details/00000866.htm 转载于:https://my.oschina.net/u/868244/blog/106310
linux进程间通信:POSIX信号量
文章目录概念描述编程接口注意事项编程案例信号量基本接口使用案例信号量父子进程间通信信号量实现 两进程之间通信概念描述 英文:semaphore 简称SEM,主要用来进行进程间同步本质:内核维护的一个正整数,可对其进行各种/-操作分类…
指针小白:修改*p与p会对相应的地址的变量产生什么影响?各个变量指针的长度为多少?...
这两天敲代码碰到了一个这样的问题 代码如下: 1 #include <stdio.h>2 #include <stdlib.h>3 int main()4 {5 int num1 10;6 7 int* p&num1;8 *p 20;9 10 printf("%p\n", &num1); 11 printf("%d\…
MVC自带表单效验
废话不说,直接上代码,一看就明白 源地址:http://www.cnblogs.com/sixiangqimeng/p/3561313.html [StringLength(5,ErrorMessage "*长度小于5")][Required(ErrorMessage "*必填啊!")][Required(ErrorMessage…
mysql求每个订单的平均价_MySQL – 选择所有客户和每个客户的总订单和总价值
SELECT a.ID,a.Name,COUNT(b.Customer) totalOrders,SUM(b.value) total_valueFROM Customers aLEFT JOIN Orders bON a.ID b.CustomerGROUP BY a.ID,a.Name要么SELECT a.ID,a.Name,COUNT(b.Customer) totalOrders,COALESCE(SUM(b.value), 0) total_valueFROM Customers aLEFT…
windows server 2008设置远程桌面连接最大数量
windows server 2008设置远程桌面连接最大数量 系统默认远程桌面连接的数量为1 打开控制面板---管理工具---远程桌面服务---远程桌面会话主机设置---把"限制每个用户只能进行一个会话"勾选去掉; 然后双击连接中的RDP-Tcp---网络适配器--最大连接数 修改为…
BZOJ1002 [FJOI2007]轮状病毒(最小生成树计数)
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7125 Solved: 3878[Submit][Status][Discuss]Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的…
linux进程间通信:POSIX 共享内存
文章目录思维导图通信原理优势POSIX 共享内存 编程接口编程案例思维导图 之前学习过sysemV 的共享内存的实现及使用原理,参考linux进程间通信:system V 共享内存 POSIX 同样提供共享内存的接口,基本原理和system V的共享内存是一样的。 通信…
求二进制中1的个数(编程之美2.1)
行文脉络 解法一——除法解法二——移位解法三——高效移位解法四——查表扩展问题——异或后转化为该问题对于一个字节(8bit)的变量,求其二进制“1”的个数。例如6(二进制0000 0110)“1”的个数为2,要求算…
mysql管理用户数据库_MySQL 数据库管理(一)(用户与受权)
前言在企业信息化的过程当中,数据库中库和表都会大量存在,须要分配给管理者核实的权限进行操做合理地分配权限,可使数据库管理井井有理,各个管理者只须要关注本身负责的内容,也可避免误操做对系统形成损失1、用户与受权…
Smart-linkmonitor-link配置注意事项
一、应用场合 Smart Link用于双上行组网,Monitor Link一般用于与Smart Link的联动,配置在Smart Link的上游设备。 二、注意事项 在配置过程中,请注意以下几点: ? 1、指定实例之前请先配置MSTP实例。MSTP的实例和VLAN映射关系发生…
封装OpenCL类
以上一篇《OpenCL入门测试》为基础,将函数封装到类中,方便调用。 #include <cstdlib> #include <iostream> #include <iomanip> #include <cstring> #include <cassert> #include <windows.h> #define CL_USE_DEPRE…
linux系统调用 ftruncate设置文件大小
系统调用ftruncate可以将一个文件裁剪为指定的大小,函数描述如下: 头文件:<unistd.h> <sys/types.h>函数使用: int truncate(const char *path, off_t length); int ftruncate(int fd, off_t length);函数参数&…
剑指 offer set 22 数组中的逆序数
总结 1. 题目为归并排序的变形, 不过我完全没想到 2. 在归并排序进行字符组 merge 时, 统计逆序数. merge 后, 两个子数组是有序的了, 下次再 merge 的时候就能以 o(n) 的时间内找到某一个逆序对第二个元素的个数 转载于:https://www.cnblogs.com/xinsheng/p/3564026.html
qt信号发送间隔短而槽耗时多_Qt信号槽问题汇总 - osc_9q1dp3jk的个人空间 - OSCHINA - 中文开源技术交流社区...
1. 发送一次信号,调用多次槽函数问题在同一个类中,多次链接QObject::connect(sender, SIGNAL(signalSender(QString, int)), receiver, SLOT(onSignalSender(QString, int))); 会导致发送一次信号signalSender(QString, int) 多次调用槽函数(onSignalSen…
一劳永逸关闭Windwos默认共享
对于IPC$,找到注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA下的RestrictAnonymous项,并将键值改为1。 对于其它默认共享,在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters下&#…
springboot 集成mybatis时日志输出
application.properties(yml)中配置的两种方式: 这两种方式的效果是一样的,但是下面一种可以指定某个包下的SQL打印出来,上面这个会全部的都会打印出来。 转载于:https://www.cnblogs.com/z0909y/p/10077565.html
linux文件IO与内存映射:用户空间的IO缓冲区
文章目录用户空间IO缓冲区产生IO缓冲区 描述IO缓冲区的写模式自定义IO缓冲区用户空间IO缓冲区产生 系统调用过程中会产生的开销如下: 切换CPU到内核态进行数据内容的拷贝,从用户态到内核态或者从内核态到用户态切换CPU到用户态 以上为普通到系统调用过…
java zookeeper_Java zookeeper开发实例
1、安装zookeeper下载zk http://archive.cloudera.com/cdh5/cdh/5/配置文件tickTime2000initLimit10syncLimit5# zk数据保存目录dataDir/usr/local/zookeeper/dataclientPort2181启动:bin/zkServer.sh start客户端命令行链接:bin/zkCli.sh2、拷贝zookeep…
【转】Maven Jetty 插件的问题(css/js等目录死锁)的解决
Maven Jetty 插件的问题(css/js等目录死锁,不能自动刷新)的解决:1. 打开下面的目录:C:\Users\用户名\.m2\repository\org\eclipse\jetty\jetty-webapp\,在进入版本对应的子目录,例如8.1.3.v2012…
ORA-4031错误深入解析
报ORA-4031错误时,我们通常可以根据Oracle无法分配多少字节的内存,来判断共享池碎片的严重程度,以下是4031错误官方的解释:[oracleguoyj ~]$ oerr ORA 403104031, 00000, "unable to allocate %s bytes of shared memory (\&…
buffers与cached的区别
具体参考以下博文: 1、https://www.cnblogs.com/chenpingzhao/p/5161844.html 2、https://blog.csdn.net/heweimingming/article/details/52230293 3、http://www.cnblogs.com/zhoug2020/p/6336453.html 其中3有top命令的详解。转载于:https://www.cnblogs.com/jia…
linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)
前言 根据上文我们学习到的用户空间的IO缓冲区,操作系统为了减少系统调用的次数,节省系统开销,提出了用户空间的IO缓冲区,即为用户空间的文件读写开辟一段可以利用setvbuf配置大小的内存空间来作为文件IO缓冲区。 描述 为了在以…