【IPC】消息队列

1、IPC对象

除了最原始的进程间通信方式信号、无名管道和有名管道外,还有三种进程间通信方式,这
三种方式称之为IPC对象
IPC对象分类:消息队列、共享内存、信号量(信号灯集)
IPC对象也是在内核空间开辟区域,每一种IPC对象创建好之后都会将其设置为全局,并且
会给其分配一个编号,只要找到唯一的这个编号就可以进行通信,所以不相关的进程可以通
过IPC对象通信。
IPC对象创建好之后,会在当前系统中可见,只要不删除或者不关闭系统,就会一直存在。
查看已经创建的IPC对象:
  ipcs 查看当前系统中所有创建的 IPC 对象
  ipcs ‐q 查看创建的消息队列
  ipcs ‐m 查看创建的共享内存
  ipcs ‐s 查看信号量
  ipcrm 删除 IPC 对象
  例如: ipcrm ‐q msqid 删除标号为 msqid 的消息队列

2、消息队列的概述

2.1 消息队列的概念

消息队列是消息的链表,存放在内存中,由内核维护
消息队列的特点
1、消息队列中的消息是有类型的。
2、消息队列中的消息是有格式的。
3、消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取,编程时可以
按消息的类型读取
4、消息队列允许一个或多个进程向它写入或者读取消息。
5、与无名管道、命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删
6、每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的。
7、只有内核重启或人工删除消息队列时,该消息队列才会被删除。若不人工删除消息队
列,消息队列会一直存在于系统中。
在ubuntu 12.04中消息队列限制值如下:
每个消息内容最多为8K字节
每个消息队列容量最多为16K字节
系统中消息队列个数最多为1609个
系统中消息个数最多为16384个
System V提供的IPC通信机制 需要一个key值通过key值就可在系统内获得一个唯一的消
息队列标识符
key值可以是人为指定的,也可以通过ftok函数获得
如果多个进程想通过IPC对象通信,则必须找到唯一的标识,而唯一的标识是由key决定
的,所以只要key知道,则就可以实现多个进程通信
(另外,Posix IPC的操作稍有不同,后面补充)

2.2 ftok函数

ftok - convert a pathname and a project identifier to a System V IPC key
 
  #include <sys/types.h>
  #include <sys/ipc.h>
  key_t ftok ( const char *pathname, int proj_id );
  功能:通过文件名和目标值共同创造一个键值并返回值
  参数:
           pathname :任意一个文件名(文件名或者目录名)
         proj_id:目标值,范围一般是 0~127
  返回值:
                  成功:键值
                  失败: ‐1
  如果使用 ftok 函数获取键值,得到的键值是由 ftok 的第一个   参数对应文件的信息和第二个参数一起决定的
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{//使用ftok函数获取键值//只要保证ftok的第一个参数对应的文件和第二个参数值相同,则不管程序运行多少遍或者多少个进程或者键值//键值一定都是唯一的key_t mykey;mykey = ftok("test",666);if(mykey==-1){perror("fail to ftok");exit(1);}
printf("mykey = %#x\n", mykey);return 0;
}

3、消息队列操作

3.1创建消息队列 -- msgget()

  #include <sys/types.h>
  #include <sys/ipc.h>
  #include <sys/msg.h>
  int msgget ( key_t key, int msgflg );
          功能:创建一个消息队列,得到消息队列的 id
参数:
          key :键值,唯一的键值确定唯一的消息队列
                  方法 1 :任意指定一个数
                  方法 2 :使用 ftok 函数获取键值
          msgflg :消息队列的访问权限,
          一般设置为 IPC_CREAT | IPC_EXCL | 0777 或者 IPC_CREAT | 0777
  返回值:
          成功:消息队列的 id
        失败:‐1
查看消息队列
  ipcs ‐q
  删除消息队列
  ipcrm ‐q msqid
测试msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>int main(int argc, char const *argv[])
{key_t mykey;mykey = ftok("test", 666);if (mykey == -1){perror("fail to ftok");exit(1);}printf("mykey = %#x\n", mykey);// 通过msgget函数创建一个消息队列int msgid;msgid = msgget(mykey, IPC_CREAT | 0666);if (msgid == -1){perror("fail to msgget");exit(1);}printf("msgid = %d\n", msgid);system("ipcs -q");return 0;
}

3.2 发送消息-- msgsnd()

  # include <sys/types.h>
  # include <sys/ipc.h>
# include <sys/msg.h>
  int msgsnd ( int msqid , const void * msgp , size_t msgsz , int msgflg );
  功能:向指定的消息队列发送数据(写操作)
  参数:
  msqid
        消息队列的id
msgp
        要写入的数据,需要自己定义结构体
struct struct_name {
          long mtype ; // 消息的编号,必须大于 0
          char mtext [ 128 ]; // 消息正文,可以定义多个成员
          ...
  }
  msgsz :消息正文的大小,不包括消息的编号长度
  msgflg :标志位
          0 阻塞
          IPC_NOWAIT 非阻塞
  返回值:
          成功: 0
          失败: 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>#define N 128typedef struct 
{long msg_type; //消息类型,必须在结构体的第一个位置并且类型必须是longchar msg_text[N]; //消息正文,也可以有多个成员并且类型也可以是任意
}MSG ;#define MSG_SIZE (sizeof(MSG)-sizeof(long))
int main(int argc, char const *argv[])
{key_t mykey;mykey = ftok("test", 666);if (mykey == -1){perror("fail to ftok");exit(1);}printf("mykey = %#x\n", mykey);// 通过msgget函数创建一个消息队列int msgid;msgid = msgget(mykey, IPC_CREAT | 0666);if (msgid == -1){perror("fail to msgget");exit(1);}//printf("msgid = %d\n", msgid);system("ipcs -q");MSG msg1 ={1,"hello world"};
MSG msg2 ={3,"UCC"};MSG msg3 ={2,"giant"};MSG msg4 ={4,"美利达"};if(msgsnd(msgid,&msg1,MSG_SIZE,0)==-1){perror("fail to send");exit(1);
}if(msgsnd(msgid,&msg2,MSG_SIZE,0)==-1){perror("fail to send");exit(1);
}
if(msgsnd(msgid,&msg3,MSG_SIZE,0)==-1){perror("fail to send");exit(1);
}
if(msgsnd(msgid,&msg4,MSG_SIZE,0)==-1){perror("fail to send");exit(1);
}system("ipcs -q");return 0;
}

3.3 消息接收--msgrcv()

# include <sys/ipc.h>
# include <sys/msg.h>
  ssize_t msgrcv ( int msqid , void * msgp , size_t msgsz ,
  long msgtyp , int msgflg );
  功能:从消息队列中接收数据(读操作),接收的数据会从消息队列中删除
  参数:
  msqid
        消息队列id
  msgp
        保存接收到的数据的结构体
        struct struct_name {
                long mtype ; // 消息的编号,必须大于 0
                char mtext [ 128 ]; // 消息正文,可以定义多个成员
        }
  msgsz
        消息正文的大小
  msgtyp :设置要接收哪个消息
          0 按照写入消息队列的顺序依次读取
          > 0 只读取消息队列中消息编号为当前参数的第一个消息
          < 0 只读取消息队列中小于等于当前参数的绝对中内最小的第一个消息
 
msgflg :标志位
        0 阻塞
          IPC_NOWAIT 非阻塞
  返回值:
          成功:接收到的消息正文的长度
          失败: 1
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>#define N 128
typedef struct 
{long msg_type; //消息类型,必须在结构体的第一个位置并且类型必须是longchar msg_text[N]; //消息正文,也可以有多个成员并且类型也可以是任意
}MSG ;#define MSG_SIZE (sizeof(MSG)-sizeof(long))int main(int argc, char const *argv[])
{key_t mykey;mykey = ftok("test", 666);if (mykey == -1){perror("fail to ftok");exit(1);}printf("mykey = %#x\n", mykey);// 通过msgget函数创建一个消息队列int msgid;msgid = msgget(mykey, IPC_CREAT | 0666);if (msgid == -1){perror("fail to msgget");exit(1);}//printf("msgid = %d\n", msgid);system("ipcs -q");//通过msgrcv函数接收消息队列中的信息(读操作)
//注意:如果没有第四个参数指定的消息时,msgrcv函数会阻塞等待
MSG msg;
//如果第四个参数为0,则按照先进先出的方式读取数据//if(msgrcv(msgid,&msg,MSG_SIZE,0,0))//如果第四个参数为>0,则获取当前值得消息类型的数据
//if(msgrcv(msgid, &msg, MSGTEXT_SIZE, 2, 0) == ‐1)//如果第四个参数为<0,则获取当前值得绝对值内消息类型最小的数据if(msgrcv(msgid, &msg, MSG_SIZE, -3, 0) == -1){perror("fail to msgrcv");exit(1);}printf("recv_msg = %s\n", msg.msg_text);system("ipcs -q");return 0;
}

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

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

相关文章

15分钟,不,用模板做数据可视化只需5分钟

测试显示&#xff0c;一个对奥威BI软件不太熟悉的人来开发数据可视化报表&#xff0c;要15分钟&#xff0c;而当这个人去套用数据可视化模板做报表&#xff0c;只需5分钟&#xff01; 数据可视化模板是奥威BI上的一个特色功能板块。用户下载后更新数据源&#xff0c;立即就能获…

windows安装wsl2以及ubuntu

查看自己系统的版本 必须运行 Windows 10 版本 2004 及更高版本&#xff08;内部版本 19041 及更高版本&#xff09;或 Windows 11 才能使用以下命令 在设置&#xff0c;系统里面就能看到 开启windows功能 直接winQ搜 开启hyber-V、使用于Linux的Windows子系统、虚拟机平…

群晖7.2版本安装CloudDriver2(套件)挂载alist(xiaoya)到本地

CloudDrive是一个强大的多云盘管理工具&#xff0c;为用户提供包含云盘本地挂载的一站式的多云盘解决方案。挂载到本地后&#xff0c;可以像本地文件一样进行操作。 一、套件库添加矿神源 二、安装CloudDriver2 1、搜索安装 搜索框输入【clouddrive】&#xff0c;搜索到Clou…

获取文章分类详情

CategoryController GetMapping("/detail")public Result<Category> detail(Integer id){Category c categoryService.findById(id);return Result.success(c);} CategoryService //根据id查询分类信息Category findById(Integer id); CategoryServiceImpl …

山西电力市场日前价格预测【2023-11-20】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-20&#xff09;山西电力市场全天平均日前电价为255.39元/MWh。其中&#xff0c;最高日前电价为436.50元/MWh&#xff0c;预计出现在18:00。最低日前电价为21.61元/MWh&#xff0c;预计出…

【DevOps】Git 图文详解(三):常用的 Git GUI

Git 图文详解&#xff08;三&#xff09;&#xff1a;常用的 Git GUI 1.SourceTree2.TortoiseGit3.VSCode 中的 Git 如果不想用命令行工具&#xff0c;完全可以安装一个 Git 的 GUI 工具&#xff0c;用的更简单、更舒服。不用记那么多命令了&#xff0c;极易上手&#xff0c;不…

Rocket如何实现顺序消费

RocketMQ 支持两种消息模式 集群消费&#xff08; Clustering &#xff09;和广播消费&#xff08; Broadcasting &#xff09;。 集群消费&#xff1a;同一 Topic 下的一条消息只会被同一消费组中的一个消费者消费。也就是说&#xff0c;消息被负载均衡到了同一个消费组的多…

OpenCV技术应用(4)— 如何改变图像的透明度

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本节课就手把手教你如何改变图像的透明度&#xff0c;希望大家学习之后能够有所收获~&#xff01;&#x1f308; 目录 &#x1f680;1.技术介绍 &#x1f680;2.实现代码 &#x1f680;1.技术介绍 改变图像透明度的实…

flink中配置Rockdb的重要配置项

背景 由于我们在flink中使用了状态比较大&#xff0c;无法完全把状态数据存放到tm的堆内存中&#xff0c;所以我们选择了把状态存放到rockdb上&#xff0c;也就是使用rockdb作为状态后端存储,本文就是简单记录下使用rockdb状态后端存储的几个重要的配置项 使用rockdb状态后端…

LangChain 代理 Agent(学习笔记)

原文&#xff1a;LangChain 代理 Agent(学习笔记) - 尘叶心繁的专栏 - TNBLOG LangChain 代理 Agent(学习笔记) LangChain 代理 Agent(学习笔记) 简介Agent Zero-shot ReActStructured Input ReActOpenAI FunctionsConversationalSelf ask with searchReAct document storePlan…

cesium雷达扫描(模糊圆效果)

cesium雷达扫描(模糊圆效果) 1、实现思路 使用ellipse方法加载圆型,修改ellipse中‘material’方法重写自己的glsl来实现当前效果 1、示例源码 index.html <!DOCTYPE html> <html lang="en"><head><!<

场景交互与场景漫游-场景漫游器(6)

场景漫游 在浏览整个三维场景时&#xff0c;矩阵变换是非常关键的&#xff0c;通过适当的矩阵变换可以获得各种移动或者渲染效果。因此&#xff0c;在编写自己的场景漫游操作器时&#xff0c;如何作出符合逻辑的矩阵操作器是非常重要的&#xff0c;但这对初学者来说还是有一定难…

Java集合大总结——List的简单使用

List简单介绍 鉴于Java中数组用来存储数据的局限性&#xff0c;我们通常使用java.util.List替代数组List集合类中元素有序、且可重复&#xff0c;集合中的每个元素都有其对应的顺序索引。JDK API中List接口的实现类常用的有&#xff1a;ArrayList、LinkedList和Vector。 List…

【腾讯云云上实验室-向量数据库】TAI时代的数据枢纽-向量数据库 VectorDB

一、向量数据库的发展历程和时代机遇 回顾向量数据库的发展历程&#xff1a; 2012年开始&#xff0c;深度神经网络的发展催生了向量数据库的发展&#xff1b;2015年至2016年&#xff0c;Google和微软发布了标志性的论文&#xff1b;2017年&#xff0c;Facebook开源了Faiss框架…

生物信息基础:实用Git命令,掌握这些就够了

我发现有搞了几年生信的朋友还不会用Github管理代码&#xff0c;这不免令人意外。我一直强调基础知识的重要性&#xff0c;而这些知识又是可以在短时间内掌握的。Github管理平时写的代码&#xff0c;要用到Git命令。虽然官方Git命令非常多&#xff0c;但我们只要掌握常用的几个…

PyTorch微调终极指南2:提升模型的准确性

作为一名机器学习从业者&#xff0c;你可能经常会发现自己处于这样一种情况&#xff1a;你正在针对特定任务微调预先训练的模型&#xff0c;但已经达到了无法进一步提高模型准确性的地步。 在本文中&#xff0c;我们将探讨可用于提高模型准确性的各种技术和策略。 这些方法旨在…

Python武器库开发-flask篇之session与cookie(二十六)

flask篇之session与cookie(二十六) 在 Flask 中&#xff0c;可以使用 session 来在不同请求之间存储和传递数据。Session 在客户端和服务器端之间交换&#xff0c;但是数据存储在服务器端。 Session 与 Cookie 的区别 session 和 cookie 都可以用来在不同请求之间存储和传递…

Vue3-readonly(深只读) 与 shallowReadonly(浅只读)

Vue3-readonly(深只读) 与 shallowReadonly&#xff08;浅只读&#xff09; readonly(深只读)&#xff1a;具有响应式对象中所有的属性&#xff0c;其所有值都是只读且不可修改的。shallowReadonly(浅只读)&#xff1a;具有响应式对象的第一层属性值是只读且不可修改的&#x…

使用requests库进行网络爬虫:IP请求错误的解决方法

目录 引言 一、了解requests库 二、遇到的问题 三、解决方法 1、随机化IP地址 2、减少请求频率 3、使用User Agent模拟浏览器行为 4、使用Cookies 四、注意事项 五、使用代理池 六、总结 引言 在利用Python的requests库进行网络爬虫操作时&#xff0c;我们有时会遇…

系列七、JVM的内存结构【堆(Heap)】

一、概述 一个JVM实例只存在一个堆内存&#xff0c;堆内存的大小是可以手动调节的。类加载器读取了类文件后&#xff0c;需要把类、方法、常变量放到堆内存中&#xff0c;保存所有引用类型的真实信息&#xff0c;以方便执行器执行&#xff0c;堆内存分为三个部分&#xff0c;即…