进程间通信的方式(三):消息队列
消息队列是在两个不相关进程间传递数据的一种简单、高效方式,她独立于发送进程、接受进程而存在。消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为是一个管道,接收进程可以独立地接收含有不同管道的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。消息队列与命名管道一样,每个数据块都有一个最大长度的限制。我们可以将每个数据块当作是一种消息类型(频道),发送和接收的内容就是这个类型(频道)对应的消息(节目),每个类型(频道)相当于一个独立的管道,相互之间互不影响。
1.概述
消息队列可以是一种消息链表。有足够的权限的线程可以往队列中放置消息,有足够读权限的线程可以从队列中取走消息。每个消息都是一个记录,它由发送者赋予一个优先级。在某个进程往一个队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达。这根管道和FIFO是相反的,对于后者来说,除非读出者已经存在,否则现有 写入者是没有意义的。
一个进程可以往某个队列中写入一些消息,然后终止,再让另外一个进程在以后某个时刻读出这些消息。我没说过消息队列具有随内核的持续性,这跟管道和FIFO不一样,当一个管道和FIFO的最后一次关闭发生时,仍然在该管或FIFO上的数据将被丢弃。
1.1 消息队列结构
我们将内核中的某个特定的消息队列画为一个消息链表。假设有一个具有三个消息的队列,消息长度分别为1字节、2字节和三字节,而且这些消息就是以这样的顺序写入该队列的。再假设这三个消息的类型(type)分别是100、200、300。
1.2 消息队列和管道的对比
1.匿名管道是跟随进程的,消息队列是跟随内核的,也就是说进程结束之后,匿名管道就死了,但是消息队列还会存在(除非显示调用函数销毁)
2.管道是文件,存放在磁盘上,访问速度慢,消息队列是数据结构,存放在内存,访问速度快
3.管道是数据流式存取,消息队列是数据块式存取
2 代码实现消息队列的通信
首先从宏观的角度了解一下消息队列的工作机制。因为消息队列独立于进程而存在,为了区别不同的消息队列,需要以key值标记消息队列,这样两个不相关进程可以通过事先约定的key值通过消息队列进行消息收发。例如进程A向key消息队列发送消息,进程B从Key消息队列读取消息。在这一过程中主要涉及到四个函数:
#include <sys/msg.h> # 消息队列相关函数及数据结构头文件int msgctl(int msqid, int cmd, struct msqid_ds *buf);# 控制消息队列函数int msgget(key_t key, int msgflg); # 创建消息队列,key值唯一标识该消息队列int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);# 接收消息int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);# 发送消息
server 消息接收方
# msg1.c 接收端#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h> # 包含消息队列相关函数及数据结构的头文件
struct my_msg_st {long int my_msg_type;char some_text[BUFSIZ];
};# 消息格式
int main()
{int running = 1;int msgid;struct my_msg_st some_data;long int msg_to_receive = 0;msgid = msgget((key_t)1234, 0666 | IPC_CREAT);# 创建标识符为key = 1234 的消息队列,注意发送端与接收端该值的一致性if (msgid == -1) {fprintf(stderr, “msgget failed with error: %d\n”, errno);exit(EXIT_FAILURE);}# 错误处理:msgget调用成功返回消息队列标识符,调用失败返回-1while(running) {if (msgrcv(msgid, (void *)&some_data, BUFSIZ,msg_to_receive, 0) == -1) { # 从消息队列接收消息,如果接收失败执行if语句并退出fprintf(stderr, “msgrcv failed with error: %d\n”, errno);exit(EXIT_FAILURE);}printf(“You wrote: %s”, some_data.some_text);if (strncmp(some_data.some_text, “end”, 3) == 0) { # 如果接收到文本含有“end”,将running设置为0,效果是:退出while循环running = 0;}}if (msgctl(msgid, IPC_RMID, 0) == -1) { # 删除消息队列,如果删除失败执行if语句并退出fprintf(stderr, “msgctl(IPC_RMID) failed\n”);exit(EXIT_FAILURE);}exit(EXIT_SUCCESS);
}
client 客户端消息发送方
# msg2.c 发送端#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#define MAX_TEXT 512
struct my_msg_st {long int my_msg_type;char some_text[MAX_TEXT];
};# 消息格式,与接收端一致
int main()
{int running = 1;struct my_msg_st some_data;int msgid;char buffer[BUFSIZ];msgid = msgget((key_t)1234, 0666 | IPC_CREAT);# 创建消息标识符key = 1234的消息队列。如果该队列已经存在,则直接返回该队列的标识符,以便向该消息队列收发消息if (msgid == -1) {fprintf(stderr, “msgget failed with error: %d\n”, errno);exit(EXIT_FAILURE);}# 错误处理,同接收者msg1while(running) {printf(“Enter some text: “);fgets(buffer, BUFSIZ, stdin);# 由控制台输入文本,并将其存放在buffer之中some_data.my_msg_type = 1;# 类型填充,在本例中没有特别含义strcpy(some_data.some_text, buffer);# 将buffer数据复制到some_text之中if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) { # 向消息队列发送消息,如果发送失败执行if语句并退出fprintf(stderr, “msgsnd failed\n”);exit(EXIT_FAILURE);}if (strncmp(buffer, “end”, 3) == 0) {# 如果发送的“end”,则在发送“end”之后,退出while,结束程序running = 0;}}exit(EXIT_SUCCESS);
}
进程间通信的方式(三):消息队列相关推荐
- exit函数_Linux进程间通信详解(三) 消息队列及函数
消息队列的概念 消息队列就是一个消息的链表,每个消息队列都有一个队列头,用结构struct msg_queue来描述.队列头中包含了该队列的大量信息,包括消息队列的键值.用户ID.组ID.消息数目.读 ...
- Linux进程间通信详解(三) —— 消息队列及函数
消息队列的概念 消息队列就是一个消息的链表,每个消息队列都有一个队列头,用结构struct msg_queue来描述.队列头中包含了该队列的大量信息,包括消息队列的键值.用户ID.组ID.消息数目.读 ...
- linux 进程uhxuhao,linux 进程间通信三 消息队列以及实例
转自 http://blog.csdn.net/liang890319/article/details/8280934 代码来自:嵌入式Linux应用开发标准教程 消息可以理解为写信给某个人,这里在应 ...
- Linux进程间通信二 System V 消息队列简介与示例
1. SystemV消息队列简介 消息队列,顾名思义即是存放消息的队列,内核为每个SystemV 维护了一个msg_queue的结构体,里面记录了每个消息队列的信息. struct msg_queue ...
- Linux 下的进程间通信:管道、消息队列、共享文件、共享内存
Table of Contents 无名管道 命名管道 消息队列 共享文件 示例 1. 生产者程序 示例 2. 消费者程序 共享内存 示例 3. memwriter 进程的源程序 示例 4. memr ...
- linux进程间通信:system V消息队列
文章目录 基本介绍 编程接口 代码实例 消息队列的发送和接收 消息队列中的消息对象的属性控制 基本介绍 支持不同进程之间以消息(messages)的形式进行数据交换,消息能够拥有自己的标识,且内核使用 ...
- Linux进程间通信--消息队列(Message queuing)
今天我们来谈一谈Linux进程间通信的方式之一消息队列 我们先来看看关于消息队列的定义: 1.消息队列是消息的链表,存放在内核中并由消息队列标识符表示. 2.消息队列提供了一个从一个进程向另一个进程发 ...
- 210127阶段三进程间通信-消息队列
目录 一.学习的知识点 1 回顾 1.1 1.2 2 进程间通信 2.1进程间通信的目的 2.2 进程间通信 2.2.1 消息队列 二.上课没有听懂或者没有理解的地方 三.当天学习的收获 一.学习的知 ...
- Linux 环境进程间通信(三):消息队列
本系列文章中的前两部分,我们探讨管道及信号两种通信机制,本文将深入第三部分,介绍系统 V 消息队列及其相应 API. 消息队列(也叫做报文队列)能够克服早期unix通信机制的一些缺点.作为早期unix ...
- linux进程间通信:POSIX 消息队列
文章目录 基本介绍 相关编程接口 编程实例 消息队列通信实例 消息队列属性设置实例 基本介绍 关于消息队列的基本介绍,前面在学习system V的消息队列时已经有过了解,linux进程间通信:syst ...
最新文章
- 一文了解点特征直方图
- python3--装饰器
- Mockito:一个强大的用于Java开发的模拟测试框架
- 吴恩达 coursera ML 第十三课总结+作业答案
- Python爬虫学习系列教程
- 查询某一个表的字段和数据类型
- ubuntu 16.04 安装mysql
- python ini
- Matlab:批量文件命名
- C++_类和对象_对象特性_构造函数和析构函数---C++语言工作笔记040
- C#学习历程(四)[实际问题]
- 邮件服务器pop3和imap,POP3服务器和IMAP服务器
- linux安装ADS软件,Ubuntu 10.10下安装ADS 2009 Update1
- hp mfp scan点配置没有反应_HP LaserJet Pro MFP M125-M126,扫描文件HPScan不能用?
- qtabwidget设置表头_QTableWidget添加表头菜单 并 可以通过表头菜单隐藏选中列
- 对偶式与反函数_图解数字电路中标准式的对偶式和反函数求解
- 山西台达plc可编程控制器_汇川PLC可编程控制器的功能特点
- 关于ksps(A/D转换速率单位)
- android 看图片tv版,易图浏览_易图浏览TV版APK下载_电视版 for 安卓TV_ZNDS软件
- 【nRF Connect】一、下载方法及简介