Linux 进程间通信(共享内存+消息队列)

news2024/11/18 15:43:42

目录

一.共享内存

1.底层原理和系统接口

a.底层原理

b.系统接口

① shmget

② shmat

③ shmdt

④ shmctl

c.命令行控制指令

2.共享内存的通信特点

a.共享内存间的通信没有任何的同步机制

b.共享内存是所有进程间通信速度最快的

c.共享内存可以提供较大的空间。

3.OS对共享内存的管理

4.*代码级实现~

源码链接

二.消息队列

1.消息队列的主要特点

2.消息队列系统接口

a. msgget

b. msgsnd

c. msgrcv

d. msgctl

3.命令行控制指令


我们知道,进程间通信的本质就是让不同的进程看到同一份资源,由于资源的不同,进程间通信的方式也就不同,上篇文章博主主要讲解了基于管道的进程间通信,这篇文章,则主要讲解基于共享内存和消息队列的进程间通信。

一.共享内存

共享内存,顾名思义,就是让不同的进程使用同一份物理内存上的空间,从而实现进程间通信。

1.底层原理和系统接口

a.底层原理

物理内存上开辟一份空间,用过用户级页表,将其映射到进程地址空间上的共享区内,并生成空间首地址返回给用户,而不同的进程便可通过其地址空间上共享区内的空间地址,共享物理内存上的同一块空间,从而实现不同进程间的通信!

大体细节,图解如下:

通过上述原理详解,我们知道,基于共享内存进行进程间通信,大致有两步:①开辟一份物理内存;②将开辟出来的物理内存地址与进程地址空间上的地址建立映射关系(与进程建立关系)。这样一来,用户便能通过进程向共享空间中进行数据IO了~~

待进程通信结束后,咱们如果想要释放某块共享内存,也有两步骤,即先接触内存与进程地址空间的映射关系,再释放共享内存。

好巧不巧,为实现上述功能,系统已经为我们安排好了专门的系统调用接口~~

b.系统接口

① shmget

int shmid = shmget(key_t key,size_t size,int shmflg);   

作用:OS开辟一块物理内存,返回值是物理内存的入口(进程层面)

参数详解

第一个参数 key : 相当于进入一个内存空间的秘钥,不同的进程通过同一个 key 找到目标共享内存,为确保key值的唯一性,常与 ftok() 函数连用,该函数通过特殊的算法,可以将文件路径和进程id转化成一个具有唯一性的整型值,供给key使用。

第二个参数 size : 表示所创建的共享内存的大小,单位是“字节”,一般是4096的整数倍。

第三个参数 shmflg :IPC_CREAT 表示,若 key 不存在,就创建;若存在,就获取并返回;IPC_CREAT | IPC_EXCL 表示,若 key 不存在,就创建;若存在,就出错返回。

② shmat

void* shmaddr = shmat(int shmid, const void *shmaddr, int shmflg); 

作用:OS将指定的物理内存映射到进程地址空间,返回值是映射到地址空间上的地址 shmaddr,上层用户可以将 shmaddr 当做一个数组来使用。

参数详解

第一个参数 shmid :共享内存的标识符,该标识符由 shmget 函数返回。

第二个参数 shmaddr :指定共享内存出现在进程内存地址的什么位置。如果直接指定为NULL,则让内核自己决定一个合适的地址位置。

第三个参数 shmflg :指定共享内存的映射选项。SHM_RDONLY表示以只读方式连接共享内存段,否则默认为读写方式(0)

③ shmdt

int shmdt(const void* shmaddr); 

作用:解除一个物理内存和进程地址空间的映射关系,参数就是 shmat 函数的返回值。

④ shmctl

int shmctl(int shmid,int cmd,struct shmid_ds *buf); 

作用:控制某一物理内存,包括将其删除等操作。

参数详解

第一个参数 shmid :共享内存标识符,即要控制的共享内存段的标识符,shmget 函数的返回值。

第二个参数 cmd :控制命令,用于指定要执行的操作。常用的命令包括IPC_STAT(获取共享内存的状态)、IPC_SET(改变共享内存的状态)、IPC_RMID(删除共享内存段)等。

第三个参数 buf :指向struct shmid_ds结构的指针,用于存储或传递共享内存段的信息。对于IPC_STAT命令,该结构用于接收共享内存的状态信息;对于IPC_SET命令,该结构用于提供新的状态信息(如权限、所有者等)。如果不需要传递或接收信息,可以设置为NULL。

c.命令行控制指令

ipcs -m  查看已经存在了的共享内存.

ipcrm -m + shmid  删除标识为 shmid 的共享内存.

将 ipcs  -m 这一指令每隔一秒运行一次:while : ; do ipcs -m ; sleep 1 ; done

注意:共享内存的生命周期是随内核的,不随进程的结束而终止,需用户手动写代码关闭!!

2.共享内存的通信特点

a.共享内存间的通信没有任何的同步机制

共享内存是直接裸露给所有使用者的,一定要注意共享内存的使用安全问题,我们可以结合互斥锁、条件变量或管道等机制来实现共享内存的同步机制。

b.共享内存是所有进程间通信速度最快的

数据拷贝次数少:共享内存允许多个进程直接访问同一块物理内存区域,数据交换和通信过程中无需通过系统内核或其他中间媒介进行数据的复制或移动。相比之下,其他IPC机制(如命名管道、消息队列等)通常需要将数据从用户空间拷贝到内核空间,再从内核空间拷贝到另一个用户空间,这一过程增加了额外的开销。

②内存映射:在共享内存中,多个进程将同一块物理内存映射到它们各自的虚拟地址空间中,这使得进程可以直接通过指针访问共享内存(就像一个数组,无需通过系统调用或其他复杂的操作。

c.共享内存可以提供较大的空间。

3.OS对共享内存的管理

系统中同时存在多个共享内存,OS对这些内存进行管理,如何管理??—— 先描述,在组织!!

即,当某一块共享内存被开辟时,OS会先创建一个存有该共享内存属性数据的结构体对象,然后再将该对象链入特定的数据结构中,这样一来,OS对共享内存的管理,就变成了对特定数据结构中某个结构体对象的增、删、查、改!!

由于同一块共享内存可能被多个进程所使用,所以,该结构体内需要有一个“引用计数”,用来表征与内存建立映射关系的进程数,只有当该引用计数为0时,才能释放这块内存~~

由于共享内存可能同时存在多份,那么如何保证第二个之后的参与通信的进程,看到的就是目标共享内存呢?--- 所以,要求每块共享内存都要有一个具有唯一性的字段(key),用于标识自身!

用于管理共享内存的结构体类型:struct shmid_ds{ 引用计数、key值、空间大小、权限...... 等};

4.*代码级实现~

源码链接

https://gitee.com/Coder-Li-YuJie/naming-pipes-and-shared-memory

二.消息队列

消息队列是一种在分布式系统中常用的应用间通信方法,它主要解决的是应用解耦、异步消息处理、流量削峰等问题。消息队列允许一个或多个生产者发送消息到一个共享的队列中,而一个或多个消费者可以从这个队列中取出消息并处理它们。这种方式使得生产者和消费者之间不需要直接通信,它们只需与消息队列进行交互,从而降低了系统的耦合度,提高了系统的可扩展性和容错性。

1.消息队列的主要特点

解耦:生产者和消费者不需要直接通信,它们之间的依赖关系被消息队列解耦。生产者只需关注如何将消息发送到队列,而消费者只需关注如何从队列中接收消息并处理。

异步处理:生产者将消息发送到队列后,可以立即返回继续处理其他任务,而不需要等待消费者的响应。这样可以显著提高系统的响应速度和处理能力。

流量削峰:在高峰期,生产者可能会产生大量的消息,这些消息会暂时存储在消息队列中,等待消费者逐一处理。这样可以避免直接冲击后端服务,起到“削峰填谷”的作用。

负载均衡:多个消费者可以从同一个队列中消费消息,队列可以根据一定的策略(如轮询、优先级等)将消息分发给不同的消费者,从而实现负载均衡。

消息可靠性:消息队列通常提供消息持久化功能,确保即使发生系统故障,消息也不会丢失。同时,一些消息队列还支持消息确认机制,只有消费者成功处理消息后,消息才会从队列中删除。

2.消息队列系统接口

a. msgget

int msgget(key_t key, int msgflg);

创建一个消息队列。功能与 shmget 类似,参数 key 和 msgflg 与 shmget() 函数中的 key、shmflg作用一摸一样,就不在此赘述~~

b. msgsnd

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

将数据写入到指定的消息队列中

参数一 msqid:消息队列的标识符,也是 msgget() 的返回值。

参数二 msgp:指向要发送的消息的指针,消息的第一个字段必须是ong类型,表示消息类型。

参数三 msgsz:消息的大小(不包括消息类型字段)。

参数四 msgflg:控制消息发送行为的标志位,如 IPC_NOWAIT 表示非阻塞发送。

c. msgrcv

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

从指定的消息队列中读取数据

参数一 msqid:消息队列的标识符,也是 msgget() 的返回值。

参数二 msgp:用于接收数据的接收缓冲区的指针。

参数三 msgsz:接收缓冲区大小(不包含消息类型字段)。

参数四 msgtyp:指定要接收的消息类型,0表示接收队列中的第一个消息,大于0表示接收类型等于 msgtyp 的第一个消息,小于0表示接收类型等于或小于 msgtyp 绝对值的第一个消息。

参数五 msgflg:控制消息接收行为的标志位,如0表示阻塞接收。

d. msgctl

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

参数一 msqid:消息队列的标识符,也是 msgget() 的返回值。

参数二 cmd:指定要执行的操作,如IPC_STAT用于获取消息队列的状态,IPC_SET用于设置消息队列的属性。

参数三 buf:指向msqid_ds结构的指针,用于存储或接收消息队列的属性。

3.命令行控制指令

命令行查看消息队列的指令——ipcs    -q

命令行删除消息队列的指令——ipcrm  -q

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

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

相关文章

网络游戏通信方案概述

弱联网和强联网游戏 长连接和短连接游戏 Socket、Http、FTP 总结

亚马逊AI编程工具Amazon Q 和 Amazon CodeWhisperer使用教程

Amazon CodeWhisperer 主要功能:用于代码生成和编程辅助。它可以在 IDE 中提供代码建议、自动补全代码、生成代码片段等。使用场景:主要用于开发者在编写代码时提高效率,减少重复性工作。特点:支持多种编程语言,集成在…

composer环境变量(phpstudy集成环境)无法使用问题

composer 不是内部或外部命令,也不是可运行的程序 或批处理文件。 按下WinR组合键打开“运行”,输入sysdm.cpl 回车,打开“系统属性”并切换至“高级”选项卡,点击“环境变量”进行配置 配置完后点击确定,重新打开命令行&#x…

leetcode:LCR 169. 招式拆解 II(python3解法)

难度:简单 某套连招动作记作仅由小写字母组成的序列 arr,其中 arr[i] 第 i 个招式的名字。请返回第一个只出现一次的招式名称,如不存在请返回空格。 示例 1: 输入:arr "abbccdeff" 输出:a示例 2…

mac Wireshark You do not have permission to capture on device “rvio“.

原因: 权限不足 解决方案: 打开终端在终端输入 whoamin (会在终端显示本机的实际用户名字) 例如:xiaoming进入 /dev 目录 cd /dev输入命令:ls -la | grep bp输入命令:sudo chown whoamin xiaoming:admin bp*重新打开 …

随机掉落的项目足迹:Vue3 + wangEditor5富文本编辑器——toolbar.getConfig() 查看工具栏的默认配置

问题引入 小提示:问题引入是一个讲故事的废话环节,各位小伙伴可以直接跳到第二大点:问题解决 我的项目不需要在富文本编辑器中引入添加代码块的功能,于是我寻思在工具栏上把操作代码的菜单删一删 于是我来到官网文档工具栏配置 …

物联网系统中OLED屏主流驱动方案详解

01 物联网系统中为什么要使用OLED驱动芯片 卓越的显示效果 1、高对比度和鲜艳色彩:OLED屏幕能够自发光,因此能够实现极高的对比度和鲜艳的色彩表现,这在物联网设备的显示界面上尤为重要,可以为用户提供更清晰、更生动的视觉体验…

next 从入门到精通

next 从入门到精通 相关链接 演示地址 演示地址 源码地址 源码地址 获取更多 获取更多 hello 大家好,我是 数擎科技,今天来跟大家聊聊 Next.js 如果你遇到任何问题,欢迎联系我 m-xiaozhicloud 什么是 Next.js Next.js 是一个基于 Reac…

从零开始搭建UVM平台(四)-加入interface

书接上回: 从零开始搭建UVM平台(一)-只有uvm_driver的验证平台 从零开始搭建UVM平台(二)-加入factory机制 从零开始搭建UVM平台(三)-加入objection机制 加入interface 上述代码还有一个问题…

目标检测论文常用评价指标(Evaluation Metrics)总结

评价指标(Evaluation Metrics) 混淆矩阵(Confusion Matrix)归一化混淆矩阵(Normalized Confusion Matrix)精确度(Precision)召回率(Recall)F1值(F…

连续4年!容联云荣登2024北京民营企业百强榜单

近日,北京市工商联发布2024北京民营企业百强“14”榜单。容联云荣登北京民营企业科技创新前100强,同时位列12家朝阳区科技百强企业之一。 自2018年起,在中共北京市委统战部的指导下,北京市工商业联合会联合有关部门,每…

springboot+satoken实现刷新token(值变化)

欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 springbootsatoken实现刷新token satoken是什么?支持什么?为什么需要&…

CSDN 账号已经恢复,后续可能会把专栏内容整理成纸质书出版

笔者曾经系统地将自己在 ABAP,SAP UI5 和 SAP OData 开发领域的知识和经验,整理输出成四套开发教程: 零基础快速学习 ABAPSAP Fiori Elements 从入门到进阶SAP OData 开发实战教程 - 从入门到提高一套适合 SAP UI5 开发人员循序渐进的学习教…

Python酷玩之旅_如何连接MySQL(mysql-connector-python)

前言 Python作为数据科学、机器学习等领域的必选武器,备受各界人士的喜爱。当你面对不同类型、存储于各类介质的数据时,第一时间是不是要让它亮个相?做个统计,画个图表,搞个报表… 等等。 正如Java中的JdbcDriver一样…

以“棋”启智,乐在其中:二近制AI智能棋盘内含9种经典玩法让老人小孩爱不释手

近年来,人工智能算法被广泛地应用到生活的各个领域,棋类游戏亦是如此。各种搭载 A 智能算法的棋盘层出不穷,以“棋”启智,乐在其中成为了当下较流行地全民益智游戏之一。 棋类游戏为何屡受欢迎? 棋类游戏是一种能够激发民族智慧…

济南奇牛科技移动办公手机安全管理平台功能说明

济南奇牛信息科技有限公司自主研发的企业移动安全管理平台为企业提供一整移动终端安全解决方案,为解决企业在实施移动终端应用系统中会遇到的安全、应用管理和资产管理方面的问题,建立统一安全策略,解决企业数字化资产安全和员工隐私保护问题…

【教学类-23-02】20240929《不会写学号的中班幼儿的学号描字贴》(中2班描字)

背景需求: 今天给孩子们做中班操作材料包《练眼力》,希望他们在操作纸左上角写学号,结果有不少孩子嚷:“我不会写学号!” “不会写的孩子举手,老师给你们做个字帖” 结果有不少孩子都举手了,我…

opencv学习:Harris角点检测和SIFT(尺度不变特征变换)算法完整代码实现

Harris角点检测 概念 Harris角点检测是一种在图像处理和计算机视觉领域广泛使用的技术,用于检测图像中的角点。角点是图像中两条边缘交点的位置,它们在图像分析、目标识别和图像配准等任务中非常重要。 角点:图像中的角点是指图像局部区域…

GDB :代码调试工具

文章目录 一、启动GDB二、GDB的基本命令1. 显示代码2. 运行程序3. 设置断点4. 单步执行5. 查看变量和内存6. 查看函数调用堆栈7. 修改变量值8. 退出GDB 一、启动GDB 在终端中,使用以下命令启动GDB并加载你的可执行文件: gdb ./your_program会进入以下界…

应用性能管理工具-SkyWalking

前言 随着微服务架构的流行,一次请求往往需要涉及到多个服务,因此服务性能监控和排查就变得更复杂,因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决…