Linux进程通信——消息队列

2023-11-02

消息队列概述

消息队列是存在Linux内核中,以链表形式来存消息
一个消息队列由一个标识符(即队列ID)来标识。
用户进程可以向消息队列添加消息,也可以向消息队列读取消息。

特点
消息队列是面向记录的,其中的消息具有特定的格式(结构体保存)
消息队列独立于发送与接收进程,哪怕进程退出后消息还会保存
消息队列中的消息是可以任意读取的,可以按照类型来读取

一般形式如下:

// 创建或打开消息队列:成功返回队列ID,失败返回-1
int msgget(key_t key, int flag);
// 添加消息:成功返回0,失败返回-1
int msgsnd(int msqid, const void *ptr, size_t size, int flag);
// 读取消息:成功返回消息数据的长度,失败返回-1
int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
// 控制消息队列:成功返回0,失败返回-1
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

消息队列发送端

#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
 struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[128];    /* message data */
           };//消息队列所用结构体

int main()
{
   struct msgbuf sendbuf = {111,"this is send program!!!"};//消息类型与发送内容
   key_t key;
   key = ftok(".",'30');//获取IPC键值
   if(key<0){
     printf("creat key number fail!\n");
   }//
     printf("%x\n",key);
   int msgid = msgget(key, IPC_CREAT|0777);//创建消息队列
   if(msgid==-1){
      printf("creat que error!\n");
      perror("why");
   }
   printf("%d\n",msgid);
   // int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
   msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);//发送消息
   msgctl(msgid, IPC_RMID,NULL);//删除队列
   return 0;
}

我们将“this is send programm!!!”发送到消息队列中

消息队列接收端

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
 struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[128];    /* message data */
           };

int main()
{
   struct msgbuf readbuf;
   key_t key;
   key = ftok(".",'1');
   int msgid = msgget(key, IPC_CREAT|0777);
   if(msgid==-1){
      printf("creat que error!\n");
      perror("why");
   }
   msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),111,0);//一样的键值和类型
   printf("%s\n",readbuf.mtext);
   printf("get success\n");


}

效果如下:
在这里插入图片描述
当同时运行两个程序时,消息就能接收

补充key值作用

进程间通信(IPC)
有两个东西可以标识一个IPC结构:标识符(ID)和键(key)。

键值(ID)
ID是IPC结构的内部名,用来确保使用同一个通讯通道(比如说这个通讯通道就是消息队列)。内部即在进程内部使用,这样的标识方法是不能支持进程间通信的。

标识符(key)
key就是IPC结构的外部名。当多个进程,针对同一个key调用get函数(msgget等),这些进程得到的ID其实是标识了同一个IPC结构。多个进程间就可以通过这个IPC结构通信。

消息队列互相发送接收

我们分为夫妻两个进程
互相发送消息
夫进程如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
 struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[128];    /* message data */
           };

int main()
{
   struct msgbuf readbuf;
   struct msgbuf sendbuf = {520,"form husband:you are my wife!love you so much"};
   key_t key;
   key = ftok(".",30);
   if(key<0){
     printf("creat key number fail!\n");
   }
     printf("%x\n",key);
   int msgid = msgget(key, IPC_CREAT|0777);
   if(msgid==-1){
      printf("creat que error!\n");
      perror("why");
   }
   printf("%d\n",msgid);
   // int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
   msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
   msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),1314,0);
   printf("%s\n",readbuf.mtext);
   msgctl(msgid,IPC_RMID,NULL);
   return 0;
}

妻进程

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
 struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[128];    /* message data */
           };

int main()
{
   struct msgbuf readbuf;
   struct msgbuf sendbuf = {1314,"form wife:you are my husband!love you so much"};
   key_t key;
   key = ftok(".",30);
   if(key<0){
     printf("creat key number fail!\n");
   }
     printf("%x\n",key);
   int msgid = msgget(key, IPC_CREAT|0777);
   if(msgid==-1){
      printf("creat que error!\n");
      perror("why");
   }
   printf("%d\n",msgid);
   // int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
   msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
   msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),520,0);
   printf("%s\n",readbuf.mtext);
   msgctl(msgid,IPC_RMID,NULL);
   return 0;
}

在这里插入图片描述
两个进程通信可以使用相同的key值但接收和发送通道的类型要不同!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux进程通信——消息队列 的相关文章

随机推荐

  • Vue中组件和插件有什么区别?

    一 组件是什么 组件就是把图形 非图形的各种逻辑均抽象为一个统一的概念 组件 来实现开发的模式 在Vue中每一个 vue文件都可以视为一个组件 组件的优势 降低整个系统的耦合度 在保持接口不变的情况下 我们可以替换不同的组件快速完成需求 例
  • 大数据学习——Zookeeper集群搭建

    一 Zookeeper入门 1 概述 Zookeeper是一个开源的分布式的 为分布式框架提供协调服务的Apache项目 2 特点 1 Zookeeper 一个领导者 Leader 多个跟随者 Follower 组成的集群 2 集群中只要有
  • typescript开发electron程序的环境搭建过程

    1 安装nodejs 2 安装vs2013 或者vs2015 下载对应的typescript插件 3 创建项目 4 npm install g tsd 5 tsd install react global save tsd install
  • 模拟双色球系统-判断中奖情况

    package Java project 1 import java util Random import java util Scanner public class Java project 1 public static void m
  • argparser中的参数解释以及required参数在pycharm中的运行方式

    在argparser包时 其中add argumenet 函数有很多参数 name or flags 一个命名或者一个选项字符串的列表 例如 foo 或 f foo action 当参数在命令行中出现时使用的动作基本类型 nargs 命令行
  • Python 入门之控制结构 - 顺序与选择结构——第1关:顺序结构

    Python 入门之控制结构 顺序与选择结构 第1关 顺序结构 任务描述 程序最基本的结构就是顺序结构 顺序结构就是程序按照语句顺序 从上到下依次执行各条语句 本关要求学习者理解顺序结构 并对输入的三个数changeone changetw
  • 智能家居 (6) ——语音识别线程控制

    目录 语音识别线程控制代码 inputCommand h mainPro c voiceControl c 代码测试 往期文章 语音识别线程控制代码 inputCommand h include
  • fwrite函数的用法

    fwrite函数就是写文件的函数 它的函数原型如下 fwrite const void buffer size t size size t count FILE stream 可以看到这个函数的参数有四个 buffer 数据存储的地址 si
  • 点云高度归一化处理(附 python 代码)

    gt 由于不同地物之间存在着高程的差异 为了去除地形起伏对点云数据高程值的影响 所以需要根据提取出的地面点进行点云归一化处理 这一步是很多算法的基础 可以提高后续点云分类或分割的准确度等 如下图所示 gt 归一化的过程其实相对简单 遍历每一
  • 贪心算法力扣刷题练习(含思路与题解)

    贪心算法 保证每次操作都是局部最优 使得最终结果也是全局最优的 需要找到贪心的策略 使得每次的最优能保证全局最优 通常需要排序 根据排序需求 自定义比较函数 sort a begin a end vector
  • protobuf c++编程笔记

    文章目录 字段内容的定义 修饰符 字段类型 引用方式 不同字段的方法 1 optional修饰的基本类型 2 optional修饰的对象类型 3 repeated修饰的基本类型 4 repeated修饰的对象类型 序列化 反序列化 字段内容
  • Vue + 高德地图 + 三维模型

    一 创建高德的kek和密钥 根据需求选择服务平台 我选择的是web端 JS API 二 在vue中引入高德地图 在public文件下找到index html文件引入你的key值 参考 https lbs amap com demo jsap
  • Could not resolve com.android.tools.build:gradle:4.0.0.

    打开别人发过来的项目的时候gradle一直下载不下来 然后报错 尝试了很多办法 最后在用户变量种添加 Android SDK ROOT 自己的Android SDK路径 gradle 下载成功 可能遇到的具体错误问题不一样仅供参考
  • CentOS8基础篇15:防火墙命令配置

    一 防火墙服务 1 启动 关闭 重启防火墙服务 systemctl start firewalld service systemctl stop firewalld service systemctl restart firewalld s
  • ES 查询不稳定现象及解决方案

    问题描述 对于相同的查询语句 ES 查询返回不同的检索内容 示例 1 filter match content 宝骏510 order score size 10 在上面的示例中可以看到推荐句子的第二句和第三句的顺序发生了变化 产生原因 官
  • spring事务的隔离级别。如何避免脏读或者幻读

    事务隔离级别为四个等级 默认是数据库的隔离级别 需要去数据库查询一下隔离级别 1 查看当前会话隔离级别 select tx isolation 2 查看系统当前隔离级别 select global tx isolation 隔离级别 Iso
  • unity MeshCollider组件

    在应用MeshCollider组件中的一个属性 Convex 这个功能很好用 但是他也是有一个坑在里面 他的好处 当你点击之后他会自动根据模型自动生成一个碰撞器 这个是不规则的碰撞器 他的坏处 没有点击 Convex 时候 比如当你有一个物
  • Commond:命令模式

    命令模式即将请求封装为对象Commond 执行者可以执行多个操作 即执行者才是操作真正的实现者 设其为操作0 9 每个操作都封装了一个对应的Commond类 当该Commond被调用时 Commond会令执行者执行其对应的操作 用户需要执行
  • 文化:测试团队建设--读书会

    如何做管理 曾经很迷茫 一路跌跌撞撞 慢慢的发现了 想要做好管理 团队文化和团队建设也是管理的重要环节 其实在一个大的测试团队里 有很多测试同学相互之间是没有交集的 如何让大家熟悉团结起来 团队建设是其中一个方法 下面和大家分享 团队建设
  • Linux进程通信——消息队列

    Linux进程通信 消息队列 消息队列概述 消息队列发送端 消息队列接收端 补充key值作用 消息队列互相发送接收 消息队列概述 消息队列是存在Linux内核中 以链表形式来存消息 一个消息队列由一个标识符 即队列ID 来标识 用户进程可以