进程间通信之消息队列

一、什么是消息队列
unix早期通信机制之一的信号能够传送的信息量有限,管道则只能传送无格式的字节流,这无疑会给应用程序开发带来不便。消息队列(也叫做报文队列)则克服了这些缺点。

消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式。
进程可以向其中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。

消息队列分两种:
POSIX消息队列以及系统V消息队列 系统V消息队列目前被大量使用

Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。

二、在Linux中使用消息队列
Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。它的用法与其他两个System V PIC机制,即信号量和共享内存相似。

消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述符,必须提供该消息队列的键值。

#include <sys/types.h>
#include <sys/ipc.h>key_t ftok(char *pathname, char proj);

功能:返回文件名对应的键值。
pathname:文件名
proj:项目名(不为0即可)

1、msgget函数
该函数用来创建和访问一个消息队列。它的原型为:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t, key, int msgflg);  

key: 键值,由ftok获得
msgflg:标志位
返回值:与键值key相对应的消息队列的描述符。

msgflg取值:
IPC_CREAT
创建新的消息队列
IPC_EXCL
与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
IPC_NOWAIT
读写消息队列要求无法得到满足时,不阻塞。

在以下两种情况下,将创建一个新的消息队列:
如果没有与键值key相对应的消息队列,并且msgflg中包含了IPC_CREAT标志位。
key参数为IPC_PRIVATE

2、msgsnd函数
该函数用来把消息添加到消息队列中。它的原型为:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msqid, struct msgbuf * msgp, int msgsz, int msgflg)

功能:向消息队列中发送一条消息
msqid:消息队列描述符
msgp:消息队列指针,指向存放消息的结构
msgsz:消息数据长度
msgflg:发送标志,有意义的msgflg标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待
如果调用成功,消息数据的一分副本将被放到消息队列中,并返回0,失败时返回-1.

消息格式:

struct msgbuf
{long mtype;     // 消息类型 > 0char mtext[1];  // 消息数据的首地址  
}

3、msgrcv函数
该函数用来从一个消息队列获取消息,它的原型为:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgrcv(int msqid, struct msgbuf* msgp, int msgsz, long msgtp, int msgflg)

功能:从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指向的msgbuf结构中。在成功的读取了一条消息以后,队列中的这条消息将被删除。

msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。

调用成功时,该函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息。失败时返回-1.

4、msgctl函数
该函数用来控制消息队列,它与共享内存的shmctl函数相似,它的原型为:

int msgctl(int msgid, int command, struct msgid_ds *buf);

command是将要采取的动作,它可以取3个值,
IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值
IPC_RMID:删除消息队列

buf是指向msgid_ds结构的指针,它指向消息队列模式和访问权限的结构。msgid_ds结构至少包括以下成员:

struct msgid_ds  
{  uid_t shm_perm.uid;  uid_t shm_perm.gid;  mode_t shm_perm.mode;  
};  

成功时返回0,失败时返回-1.

三、使用消息队列进行进程间通信
马不停蹄,介绍完消息队列的定义和可使用的接口之后,我们来看看它是怎么让进程进行通信的。由于可以让不相关的进程进行行通信,所以我们在这里将会编写两个程序,msgreceive和msgsned来表示接收和发送信息。根据正常的情况,我们允许两个程序都可以创建消息,但只有接收者在接收完最后一个消息之后,它才把它删除。
发送:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>struct msgbuf 
{long mtype;     /* message type, must be > 0 */char mtext[256];  /* message data */
};int main()
{// 创建消息队列int msgid = msgget((key_t)1234, 0666|IPC_CREAT);if (msgid == -1){perror ("msgget");return -1;}struct msgbuf  msg;msg.mtype = 2;strcpy (msg.mtext, "hello");int ret = msgsnd(msgid, &msg, 256, IPC_NOWAIT);if (ret == -1){perror ("nsgsnd");return -1;}return 0;
}

接收:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>struct msgbuf 
{long mtype;     /* message type, must be > 0 */char mtext[256];  /* message data */
};int main()
{// 创建消息队列int msgid = msgget((key_t)1234, 0666|IPC_CREAT);if (msgid == -1){perror ("msgget");return -1;}struct msgbuf  msg;int ret = msgrcv(msgid, &msg, 256, 2, IPC_NOWAIT);if (ret == -1){perror ("msgrcv");return -1;}printf ("%s\n", msg.mtext);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“ 愿我如星君如月,夜夜流光相皎洁 ...”

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 永远相信爱情 ... 从一而终 ... --------------------------------------------------------------------------- 后记&#xff1a;2…

python内建函数和工厂函数的整理

内建函数参阅&#xff1a; https://www.cnblogs.com/pyyu/p/6702896.html 工厂函数&#xff1a; 本篇博文比较粗糙&#xff0c;后续会深入整理转载于:https://www.cnblogs.com/qiang-upc/p/11155786.html

显卡天梯图:2014最新显卡性能天梯图

随着电脑游戏的推广&#xff0c;很多用户都喜欢上了电脑网络游戏&#xff0c;所以组装电脑用户在装机的时候&#xff0c;会考虑电脑配置的游戏性能&#xff0c;要提高电脑配置游戏性能首要条件就是显卡性能要强&#xff0c;如果显卡性能不佳&#xff0c;那么其它方面性能再强&a…

进程间通信之分别用共享内存和信号量实现卖票

利用共享内存实现的卖票系统&#xff1a; 利用flag来保证同一时间只有一个程序使用内存&#xff0c;使用结束还原。 #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <string.h> #include <…

shiro 的 @RequiresPermissions 注解使用

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 权限控制是shiro最核心的东西 Shiro权限声明通常是使用以冒号分隔的表达式。一个权限表达式可以清晰的指定资源类型&#xff0c;允许的…

【显卡天梯图】2014年最新显卡天梯图 – 【迄今最全系列显卡】

【显卡天梯图】2014年最新显卡天梯图 – 【迄今最全系列显卡】 随着电脑游戏的推广&#xff0c;很多用户都喜欢上了电脑网络游戏&#xff0c;所以组装电脑用户在装机的时候&#xff0c;会考虑电脑配置的游戏性能&#xff0c;要提高电脑配置游戏性能首要条件就是显卡性能要强&am…

原理系列:Spark1.x 生态圈一览

Spark生态圈&#xff0c;也就是BDAS&#xff08;伯克利数据分析栈&#xff09;&#xff0c;是伯克利APMLab实验室精心打造的&#xff0c;力图在算法&#xff08;Algorithms&#xff09;、机器&#xff08;Machines&#xff09;、人&#xff08;People&#xff09;之间通过大规模…

SpringMVC 注解 : @ModelAttribute

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 SpringMVC 注解 &#xff1a; ModelAttribute 的用法如上。 转自&#xff1a;https://blog.csdn.net/lovesomnus/article/details/78873…

网络编程项目(聊天室项目)

一、实现目标 一个在Linux下可以使用的聊天软件&#xff0c;要求至少实现如下功能&#xff1a; 1. 采用Client/Server架构 2. Client A 登陆聊天服务器前&#xff0c;需要注册自己的ID和密码 3. 注册成功后&#xff0c;Client A 就可以通过自己的ID和密码登陆聊天服务器 4…

CPU天梯图:2014年最新CPU性能天梯图

用户在组装电脑的前期需要考虑怎么选择适合自己的CPU&#xff0c;现在CPU性能强的比较贵&#xff0c;便宜的CPU性能又比较差&#xff0c;选择性价比高并且适合自己的处理器还真是比较花心思。在2014年的时候&#xff0c;最主流热门的AMD处理器是AMD A10-6800K&#xff0c;最新推…

解决: idea 修改 jsp 后,页面刷新无效

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 idea 修改 jsp 后浏览器访问无效。 解决&#xff1a;进入 idea 配置 修改部署方式&#xff1a; 修改 更新文件方式&#xff1a; OK了。

Python中的getpass模块

getpass模块用于输入密码时&#xff0c;隐藏密码字符 代码 import getpass name input("请输入你的名字&#xff1a;") passwd getpass.getpass("请输入你的密码&#xff1a;")print (name,passwd)   首先我们要import引入getpass模块&#xff0c;然后…

C++之命名空间

为什么要使用命名空间&#xff1f; 一个中大型软件往往由多名程序员共同开发&#xff0c;会使用大量的变量和函数&#xff0c;不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过&#xff0c;没有问题时&#xff0c;将它们结合到一起就有可能会出现命名冲突。 …

如何做到每天写代码?

摘要&#xff1a;总有一大堆事情没有做完&#xff0c;没有时间和精力为业余项目写代码&#xff1f;不要着急&#xff0c;看看可汗学院计算机科学院院长John Resig怎么说。本文将教你如何保证在每天都能有时间给业余项目写代码。 你是否曾为业余项目没有进展而惆怅过&#xff1f…

Vue 实现前后端分离项目

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Vue实现前后端分离项目的初体验 经过之前学习的Vue的知识&#xff1a; vue基本指令vue组件vue-resourcevue路由 其实我们已经可以开始…

C++对C的一些加强和变化

实用性加强&#xff1a; int main() {// C语言中的变量都必须在作用域开始的位置定义&#xff01;&#xff01;// C中更强调语言的“实用性”&#xff0c;所有的变量都可以在需要使用时再定义。for (int i 0; i < 10; i){std::cout << i << std::endl;}return…

优秀Unix管理员的七个习惯

摘要&#xff1a;Unix系统管理员可能会很懒或喜欢优雅的解决方法&#xff0c;这就是他们的存在之美。一位优秀的Unix系统管理员有着自己的习惯&#xff1a;不会等到问题来找你、精通所使用的工具和系统、确定事情优先次序和喜欢优雅的解决方案但不迷失等。 优秀的Unix系统管理员…

Vue.js 极简小例:读值、样式调用、if判断、a 标签、点击事件、管道

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 写法&#xff1a; <template><div id"app"><!-- 三目运算符使用 ‘ok’ 的值定义在 data 中-->{{ ok …

【快写】基本思路及模板

快读也可以了解一下 先从C自带的输出开始吧 cout<<n<<endl;这是最基本的输出&#xff0c;适合初学者 &#xff08;虽然我到现在都还在用&#xff09; 然后稍微快一点的输出 printf("%d",n);这个就比较快速了&#xff0c;但是对于那种毒瘤题目 故意卡你的…

C++与C中const的比较以及const和define的比较

C与C中const的比较&#xff1a; C语言中 const修饰的变量是一个 常变量&#xff0c;本质还是变量&#xff0c;有自己的地址空间C编译器对const常量的处理 当碰见常量声明时&#xff0c;在符号表中放入常量 > 问题&#xff1a;那又如何解释取地址编译过程中若发现对const使…