当前位置: 首页 > news >正文

Linux进程通信——消息队列

概念

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。

特点

1.消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。(消息队列是结构体)
2.消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除
3.消息队列可以实现消息的随机查询,消息不一定要以先进先出的次席读取,也可以按消息的类型读取

两者的队列ID需相同才能成功实现存放数据和取数据,如图都指向队列1的最后一个。

消息队列与管道的不同点:写入读取后内容还存在于Linux内核中,不会跟管道一样读取完就消失。

创建

从消息队列特点可知,两个进程分别需要同队列ID相同的队列进行写入数据并读取数据,此时要想成功创建一个消息队列,需关心两个问题:

问题一:进程B如何添加消息到队列

问题二:进程A如何读取队列的消息

头文件

#include <sys/msg.h>

常用API

msgget()

创建或打开消息队列:成功返回队列ID,失败返回-1

int msgget(key_t key, int flag);
key是一个索引值,为非负数,将通过索引值在Linux内核找到队列
flag打开队列的方式

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

msgget(key,IPC_CREAT);

2、key参数为IPC_PRIVATE

msgget(key,IPC_PRIVATE);

msgsnd()

添加消息:成功返回0,失败返回-1

int msgsnd(int msqid, const void *ptr, size_t size, int flag);

msqid:消息队列的ID
ptr:写入的数据,指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下:

struct msgbuf
{long mtype; //消息类型,必须大于0char mtext[1];//消息文本 
};

size:数据的长度
flag:0,表示忽略,表示进程将被阻塞直到函数可以从队列中得到符合条件的消息为止;(还有许多,此处省略)

msgrcv()

读取消息:成功返回消息数据的长度,失败返回-1

int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);

msqid:消息队列的ID
ptr:写入的数据,指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下:

struct msgbuf
{long mtype; //消息类型,必须大于0char mtext[1];//消息文本 
};

type:消息类型

type = 0返回队列中的第一个消息
type >0返回队列中消息类型为 type 的第一个消息
type< 0返回队列中消息类型值小于或等于 type 绝对值的消息,如果有多个,则取类型值最小的消息

可以看出,type值非 0 时用于以非先进先出次序读消息。也可以把 type 看做优先级的权值。

size:数据的长度

flag:0,表示忽略,表示进程将被阻塞直到函数可以从队列中得到符合条件的消息为止;(还有许多,此处省略)

代码展示

get.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>struct msgbuf
{long mtype;char mtext[128];
};int main()
{int msgId;//创建消息队列IDstruct msgbuf readBuf;//定义一个读取数据的结构体msgId = msgget(1234,IPC_CREAT|0777);//在内核中打开或建立键值为1234的,权限为0777的消息队列if(msgId == -1)//如果创建失败则执行下面代码{printf("create queue failed\n");}msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),888,0);//从队列中获取888类型的数据并存放到结构体的mtext中,如果队列中未出现888类型的数据,则程序阻塞在这里,这里的888需要与写入队列类型数据一致printf("read from queue:%s\n",readBuf.mtext);struct msgbuf sendBuf = {999,"thank you for reach\n"};//读取完毕后将字符串内容写入到999类型的数据中,这里的999类型需要与读取的类型数据一致msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);//将上一行的结构体数据写入1234消息队列中return 0;
}

send.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>struct msgbuf
{long mtype;char mtext[128];
};int main()
{int msgId;struct msgbuf sendBuf = {888,"this is message from queue\n"};//将字符串内容写入到888类型的数据中,这里的888类型需要与读取的类型数据一致struct msgbuf readBuf;msgId = msgget(1234,IPC_CREAT|0777);if(msgId == -1){printf("create queue failed\n");}msgsnd(msgId,&sendBuf,strlen(sendBuf.mtext),0);//将结构体内容写入到1234消息队列中msgrcv(msgId,&readBuf,sizeof(readBuf.mtext),999,0);//写入之后从队列中获取999类型的数据并存放到结构体的mtext中,如果队列中未出现999类型的数据,则程序阻塞在这里,这里的999需要与写入队列类型数据一致printf("return form queue:%s\n",readBuf.mtext);return 0;
}

运行get.c,创建并打开键值为1234的消息队列,但此时表现为堵塞状态,因为队列里没有888类型的数据

运行send.c,创建并打开键值为1234的消息队列,往队列里写入888类型的数据,此时接收端会接受到写入端写入消息队列的数据并将其读取,同时让接收端往队列里写入999类型的数据,让写入段接受999类型的数据并读取

http://www.lryc.cn/news/238345.html

相关文章:

  • ArcGIS教程——ArcGIS工具-按线分割面
  • C语言进阶之冒泡排序
  • 零代码编程:用ChatGPT将SRT字幕文件批量转为Word文本文档
  • 力扣刷题第二十六天--二叉树
  • 电脑显示msvcp140_1.dll丢失的5个常用解决方法,亲测可修复
  • hive sql 行列转换 开窗函数 炸裂函数
  • Continuity” of stochastic integral wrt Brownian motion
  • 设置 wsl 桥接模式
  • [uni-app] uni.showToast 一闪而过问题/设定时间无效/1秒即逝
  • 7、信息打点——资产泄露CMS识别Git监控SVNDS_Store备份
  • 【运维篇】5.6 Redis server 主从复制配置
  • Hive语法,函数--学习笔记
  • LeetCode热题100——动态规划
  • 初识树(c语言)
  • 听GPT 讲Rust源代码--src/librustdoc(2)
  • 多目标应用:基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化调度(MATLAB)
  • 泉盛UV-K5/K6全功能中文固件
  • 基于JPBC的无证书聚合签名方案实现
  • FreeRTOS内存管理分析
  • hashMap索引原理
  • qcow2、raw、vmdk等镜像格式工具
  • GaussDB新特性Ustore存储引擎介绍
  • 人工智能基础_机器学习046_OVR模型多分类器的使用_逻辑回归OVR建模与概率预测---人工智能工作笔记0086
  • 【LeetCode刷题-链表】--23.合并K个升序链表
  • 强化学习笔记
  • 经典双指针算法试题(一)
  • MATLAB | 绘图复刻(十三) | 带NaN图例的地图绘制
  • netty整合websocket(完美教程)
  • 选择PC示波器的10种理由!
  • 【pytorch深度学习 应用篇02】训练中loss图的解读,训练中的问题与经验汇总