Linux:共享内存VS消息队列VS信号量

文章目录

  • 共享内存的通信速度
  • 消息队列
    • msgget
    • msgsnd
    • msgrcv
    • msgctl
  • 信号量
    • semget
    • semctl
  • 内核看待ipc资源
    • 单独设计的模块
    • ipc资源的维护

本篇主要是基于共享内存,延伸出对于消息队列和信号量,再从内核的角度去看这三个模块实现进程间通信

共享内存的通信速度

共享内存是所有进程间通信里面速度最快的,并且是没有质疑的,何以见得这个结论呢?

要说这个结论,还要从管道说起,对于进程来说,如果想要使用管道进行通信,那么首先要有进程的PCB和对应的进程地址空间,其次如果选择管道进行通信,那么就会建立管道之后,将用户自己的数据交给另外一个进程,通过write的系统调用写到缓冲区中,本质上就是把用户级的缓冲区直接经过系统调用拷贝到内核的管道中,对于读端来说,就是用read系统调用再读取信息,相当于是把内核中的数据经过read系统调用,把数据拷贝到用户空间内,此时就完成了从进程a到进程b数据通信的目的

而对于共享内存来说,创建好共享内存之后,经过挂接在自己的地址空间的共享区中就能找到这个区域,之后就可以在这个共享内存中进行写入,写入后共享内存这里就会立刻有这段信息,在这个过程中是没有任何系统调用的,写的信息立刻就能看到,没有任何延误,换而言之,这两个进程之间不需要通过内核进行拷贝,甚至都不需要用户定义的缓冲区,直接向共享内存中写入信息,用户立刻就能看到,可以理解为是把用户级别的缓冲区合并成一个缓冲区,只要进程a向里面写,进程b立刻就能看到,有效的减少了数据通信过程中经由数据拷贝造成的消耗问题

因此我们说,对于共享内存来说,它的效率体现在可以减少数据拷贝,不需要经过用户到内核,内核到用户这样的拷贝,而是直接在用户的层面上,进程a向共享内存写信息,进程b就能看到,甚至可能都不需要缓冲区的概念,所以是高效的

那能减少多少次拷贝呢?

对于这个问题来说,这里简单做个解释,具体可能会因为实际场景和配置略有差距

假设现在有输入的函数需求,数据也从键盘输入了,那么从文件的角度来讲,就相当于从文件里面读取了信息,而从文件中读取信息也算是一层拷贝,而现在有输出的需求,需要把数据输出到显示器上,而现在的数据是存储到内存或者是缓冲区中,而从内存刷新到外设这个过程,也算是一层拷贝,而实际上,CPU只认识内存,所以想要让CPU处理数据,就必须把外设的信息加载到内存中,再从内存处理后刷新到外设上,而这个过程实际上就是把数据从一个设备拷贝到另外一个设备上,凡是数据迁移,都可以看成是拷贝,所以对于管道文件来说,不管是write系统调用还是read系统调用,都是和内核进行交互,从内核交互的角度来讲,这两个函数其实就是一个拷贝的函数,那么来回进行数据的拷贝,效率自然不能和共享内存比

那么回到这个问题,到底可以减少多少次拷贝?假设现在有硬件,那么从键盘到显示器这个过程,输入数据是需要用户自己提供缓冲区,把数据从键盘读取到缓冲区中,再把数据从缓冲区拷贝到管道当中,而最终目标是要打印到显示器上,那显示器也是有对应的缓冲区的,所以就把数据再拷贝到缓冲区中,最终就能写到显示器中,这么一套理论,保守的来讲都有四次的拷贝过程,如果把语言本身提供的缓冲区也加上,只会比这个过程更多

在这里插入图片描述

那如果对于共享内存来说呢?从键盘中读取的数据,直接写到共享内存中,读取的进程只需要把共享内存中的数据显示到显示器上就可以了,此时就相当于第一次拷贝,将数据从外设写到共享内存中,第二次把共享内存中的数据写到显示器上,两次拷贝就刷新过去了,直接就省去了内核之间的拷贝过程,就算不考虑语言级别的缓冲区,也能减少两次拷贝

在这里插入图片描述

消息队列

消息队列提供一个进程给另外一个进程发送数据块的能力,那如何理解这句话呢?先画出下面的示意图

在这里插入图片描述
这是对于消息队列画出的最基本的示意图,在ipc资源当初被设计的时候,能够在内核层面上创建共享内存,创建对应的结构来管理这样的共享内存,那在操作系统层面上也可以创建一个队列,这个队列的名字就叫做msg_queue,这个队列刚开始是空的,但是用户是有数据的,通过一定的接口传递到队列中,此时就会在队列的底层形成一个一个的节点,这里可以理解成是链队列,把这个链队列链入到这个队列之中

消息队列的本质是要进行进程间通信,而只要涉及到进程间通信就离不开的话题是让两个不同的进程看到同一份资源,这也是在先前已经建立起来的思想观念,那么基于这个原因,进程a发送的消息队列中的内容必然是需要让进程b见到的,所以就有了接口:

msgget

在这里插入图片描述
它其实和共享内存是很相似的,也是从系统V中获取一个消息队列的标识符,只要调用了这个接口,那么就可以在内核中创建出一个消息队列,这个消息队列就可以使用了

那随之而来的下一个问题是,现在进程a创建出对应的消息队列,也满足了让不同的进程看到同一份资源这样的一个基本的条件,但是现在面临的问题是,如果进程a向消息队列中写信息,进程b也向消息队列中写信息,那么如何去进行区分呢?消息队列中的节点对于不同的进程来说想要看到的信息当然是不一样的,所以必然有对应的标识符,由进程a创建的数据节点中就会带有进程a的标识符,由进程b创建的节点就会有进程b的标识符,这样不同的进程在识别到某个资源中没有自己所对应的标识符就不会识别了,而是只会识别到自己对应的标识符

消息队列由于和共享内存一样,都是隶属于系统V内部的结构,所以它们之间必定会遵循一定的标准,所以从接口或是其他的层面上都几乎相似,因此消息队列的生命周期也是随内核的,而操作系统中各种各样的进程也都会有通信的需求,如果创建出各种各样的消息队列,那么操作系统也必然会为这一个一个的消息队列进行维护,所以从逻辑上讲,消息队列和共享内存基本上是一样的,所以对于消息队列的管理,就转换成了对于描述该消息队列的数据结构对象的增删查改,这样就把消息队列管理起来了

msgsnd

在这里插入图片描述
发送数据块到消息队列

msgrcv

在这里插入图片描述
获取消息队列中的数据块

msgctl

在这里插入图片描述
这个接口也和共享内存基本一致,这里不再过多描述

信号量

信号量本质上就是一种计数器,用来保护共享资源,未来可能会有多个线程看到同一个公共资源,那在执行和访问共享资源的过程中,就可能会产生问题,例如一个进程正在写信息,另外一个进程就已经来读了,那么就会产生数据干扰,这当然是不被操作系统认可的行为,为了避免这样的问题导致内部数据紊乱,所以就引入了信号量的概念,来保护操作系统内部的公共资源,这是对于信号量最初步的理解

semget

在这里插入图片描述
这是信号量的创建接口

semctl

在这里插入图片描述
这是信号量的控制接口,和消息队列以及共享内存不太一样的是,多了一个可变参数,所以对于信号量的控制相比起其他来说要略复杂一些

消息队列和共享内存都有具体管理的数据结构对象,所以对于信号量也不例外,肯定有其对应的管理对象,所以也会有对应的struct ipcperm结构体对象

对于信号量之后的其余内容,放在之后的内容里,这个模块本身主要是要对于共享内存的理解,但由于消息队列和信号量都是ipc资源,所以拿来一谈,之后对于信号量还有更多的内容补充

内核看待ipc资源

下面进行的模块是,内核是如何对待ipc资源的

上述有了三种共享资源,有共享内存,消息队列,信号量,由于这三个模块都是遵循一套标准做出来的,所以也是比较相似,例如接口的设计,数据结构的管理方式,以及返回的id值,那对于操作系统来说,是不是应该把这些也进行统一的管理呢?答案是肯定的

单独设计的模块

第一个想要输出的结论是,这个模块是操作系统内部单独设计出的模块,对于模块的概念,大体上可以细分为进程管理,内存管理,文件管理,驱动管理,这是操作系统的四大管理模块,而对于ipc资源的管理也是一个模块,只不过是下属的细分模块,不属于最大的四个管理模块,有了这个概念之后,那么在操作系统内部是如何进行管理的呢?

ipc资源的维护

ipc资源是如何在内核中进行维护的呢?现在有三种共享资源,这三种共享资源又有它们对应的id,key值,这些分散的数据理应被管理起来,事实上操作系统也确实把他们管理起来了

在这里插入图片描述
那在内核中是如何进行数据维护的呢?在操作系统内部存在这样的结构

struct ipc_id_ary
{int size;struct kern_ipc_perm *p[0];
}

这个结构体中存储的是数组元素个数以及一个柔性数组,在上图中也有对应,这里单独将其拿出分析

那生成这样的一个结构,存放的数据类型是kern_ipc_perm的一个结构体类型的指针,这个指针会指向一个指针数组,这个指针数组中存储的不是其他信息,存储的是具体的ipc资源的结构体的开头的第一个元素,这也就是为什么在内核中不管是消息队列还是共享内存还是信号量,它们的第一个元素都是一个perm类型的字样,就是为了方便于将这个内容统一管理到这样的一个结构体中,这样就能把所有的ipc资源统一用指针数组来管理起来

那这有什么用?用处就是未来可以通过这个内容找到对应的内容,在实际的使用中,可以通过数组中的一个指针,找到它对应的属于哪个共享资源,然后转换成对应的类型,有了起始地址和偏移量,整个数组内的对应元素的各种内容也就都有了,这样就能做到进行数据的访问过程

因此有了这样的结构,之后再管理所有的ipc资源的时候,在设计模式中就将所有内核结构的第一个成员设计成一样的,都是key值,未来在辨别这些ipc资源是否存在的时候,只需要遍历这个数组指针,在这个数组中找到各个内容中的key值,然后判断这个key值是否存在就可以了,如果不存在就进行创建,因此往后就可以统一用数组的方式访问对应的资源,如果想要找到对应资源中的其他信息也可以做出指针对类型做强转来定位到具体的位置

整个流程其实有些类似于C++中的多态,多态的概念已经不是第一次提出了,再对于外设作为文件系统的篇章中,已经讲述了虚拟文件系统就有些类似于多态,而在这里也是第二次提出对于多态的概念,多态就是令子类去继承基类,那么对应到ipc的模式中,每一个具体的ipc资源填充不同的属性,但是开头的元素都一样,再定义一个指针数组,指针数组都会指向一个具体的ipc资源,这就是一个典型的多态的过程

在Linux内核当中,管理System V版本的ipc资源,虽然内部实现的差异比较大,但是利用抽象的方式还是用c语言实现了多态,最终把所有的ipc资源都收拢在了一个数组中,这样对于ipc资源的管理就转换成了对于这个数组的增删查改,这样就做到了管理好共享资源

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

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

相关文章

2024 新年HTML5+Canvas制作3D烟花特效(附源码)

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

RK3568 Android 13 系统裁剪

android 13 系统裁剪是个大工程,裁剪也是需要大量的测试,才能保证系统的稳定性,以下是RK官方给出的裁剪方案,有兴趣的可以去看一下,对裁剪不是要求过高的可以根据官方的建议,对系统进行裁剪: Rockchip And…

专科拿到季军:微茫星火,奋起直追!

Datawhale干货 作者:“不啻微茫”团队,季军方案 前 言 大家好,我们是 飞桨星河社区 X 智海Mo平台 AI 大模型创意应用大赛 获奖团队——"不啻微茫",很荣幸能有机会与大家分享这次比赛经验,我们从零开始的过程…

【CanvasKeyFrames - HTML5 Canvas 图片序列帧播放工具】

前言 一、CanvasKeyFrames 是什么&#xff1f; 用来做canvas动画的工具。 二、使用步骤 效果如图&#xff1a;上下波动的线条 1.引入库 代码如下&#xff08;示例&#xff09;&#xff1a; 在html中引入&#xff1a; <script src"canvas-keyframes.js"><…

【linux】运维-磁盘空间不足-用到的命令(简洁)

【linux】运维-磁盘空间不足-用到的命令 常用&#xff1a; 注&#xff1a;du -s 和 -d 不能同时都用, -s | -d n 注&#xff1a;df -H 和 -h 区别 -H 1K1000 -h 1K1024 #-T 显示文件系统类型 -h 高可读性显示 df -Th #-c显示总和 ;sort -r 倒序显示 ;2>/dev/nul…

LiveGBS流媒体平台GB/T28181常见问题-如何快速查看推流上来的摄像头并停止摄像头推流?

LiveGBS流媒体平台GB/T28181常见问题-如何快速查看推流上来的摄像头并停止摄像头推流&#xff1f; 1、负载信息2、负载信息说明3、会话列表查看3.1、会话列表 4、停止会话5、搭建GB28181视频直播平台 1、负载信息 实时展示直播、回放、播放、录像、H265、级联等使用数目 2、负…

蓝桥杯AT24C02问题记录

问题1&#xff1a;从这个图片上可以看出这两个在IIC的.c文件里延时时间不一样&#xff0c;第一张图使用了15个_nop_(); 12M晶振机器周期是 1/12M*121uS&#xff1b;nop()要延时1个指令周期。延时时间不对会对时序产生影响&#xff0c;时序不对&#xff0c;则AT24C02有没被使用…

时序分解 | MATLAB实现CEEMDAN+SE自适应经验模态分解+样本熵计算

时序分解 | MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算 目录 时序分解 | MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现CEEMDANSE自适应经验模态分解样本熵计算 包括频谱图 附赠案例数据 可直接运行 …

秋招面试—浏览器原理篇

浏览器原理篇 1.什么是XSS、CSRF,怎么预防&#xff1f; &#xff08;1&#xff09;XSS(跨站脚本攻击)&#xff1a;攻击者将恶意代码植入到浏览器页面中&#xff0c;盗取存储在客户端的Cookie&#xff1b; ​ XSS分为&#xff1a;①存储型&#xff1a;论坛发帖、商品评论、用户…

cartographer离线建图报错:data_.trajectory_nodes.SizeOfTrajectoryOrZero

cartographer离线建图报错: data_.trajectory_nodes.SizeOfTrajectoryOrZero [FATAL] [1706177325.876019302, 1706015603.398505596]: F0125 18:08:45.000000 17607 pose_graph_2d.cc:1314] Check failed: data_.trajectory_nodes.SizeOfTrajectoryOrZero(trajectory_id) &…

C++类和对象(中)

✨Blog&#xff1a;&#x1f970;不会敲代码的小张:)&#x1f970; &#x1f251;推荐专栏&#xff1a;C语言&#x1f92a;、Cpp&#x1f636;‍&#x1f32b;️、数据结构初阶&#x1f480; &#x1f4bd;座右铭&#xff1a;“記住&#xff0c;每一天都是一個新的開始&#x1…

【BUG】联想Y7000电池电量为0且无法充电解决方案汇总

因为最近火灾很多&#xff0c;所以昨天夜晚睡觉的时候把插线板电源关掉了&#xff0c;电脑也关机了。 各位一定要注意用电安全&#xff0c;网上的那些事情看着真的很难受qvq。 第二天早上起床的时候一看发现电脑直接没电了&#xff0c;插上电源后也是显示 你一定要冲进去啊(ू˃…

Android HIDL概述与绑定模式的实现

一、前言 Android O(8.0) 版本之后&#xff0c;底层实现有了比较大的变化&#xff0c;最显著的一个方面就是 HIDL 机制的全面实施。本文对于理解系统源码中 Gnss、Usb、Camera 等模块的工作原理有极大帮助。 二、HIDL 设计目的 在 Android O(8.0) 之前系统的升级牵扯多方协作…

c语言实战之贪吃蛇

文章目录 前言效果展示游戏用到的图片游戏思路一览游戏前准备一、贪吃蛇、食物、障碍物节点坐标的结构体二、枚举游戏状态、和贪吃蛇的方向三、维护运行的结构体 游戏开始前的初始化一、学习图形库相关知识二、设置背景三、欢迎界面四、初始化贪吃蛇五、生成障碍物六、生成食物…

22.云原生之GitLab CICD实战及解析【干货】

云原生专栏大纲 文章目录 准备工作gitlab-ci.yml流水线mven打包项目制作并推送镜像kaniko方式docker方式 部署到k8s验证执行情况 GitLab Runner k8s执行器工作流程注册配置kubernetes runnerkubernetes runner配置通过修改 Pod 规范为每个构建作业创建一个 PVC自定义卷装载持久…

腾讯云Linux(OpenCloudOS)安装tomcat9(9.0.85)

腾讯云Linux(OpenCloudOS)安装tomcat9 下载并上传 tomcat官网 https://tomcat.apache.org/download-90.cgi 下载完成后上传至自己想要放置的目录下 解压文件 输入tar -xzvf apache-tomcat-9.0.85.tar.gz解压文件&#xff0c;建议将解压后的文件重新命名为tomcat,方便后期进…

如何编辑图片上的文字?分享5种可以编辑的工具!

在数字时代&#xff0c;图片已经成为信息传递的重要载体。有时候&#xff0c;我们需要在图片上添加文字&#xff0c;以增加信息的清晰度或创意性。那么&#xff0c;如何编辑图片上的文字呢&#xff1f;本文将为你揭秘编辑图片文字的必备工具&#xff0c;让你轻松实现创意表达。…

python小项目:口令保管箱

代码&#xff1a; #! python3 # python 编程-----口令保管箱passwords{emails: F7minlBDDuvMJuxESSKHFhTxFtjVB6,blog:VmALvQyKAxiVH5G8v01if1MLZF3sdt,luggage:12345,} import sys,pyperclip if len(sys.argv)<2:print(usage:python python3文件[accout]-copy accout pass…

【Linux网络编程】网络编程套接字(1)

【Linux网络编程】网络编程套接字(1) 目录 【Linux网络编程】网络编程套接字(1)源IP地址和目的IP地址端口号端口号和进程ID的关系 网络通信TCP协议UDP协议网络字节序socket编程接口简单的UDP网络程序 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2024.1.29 前言&#xff1…

《HTML 简易速速上手小册》第9章:HTML5 新特性(2024 最新版)

文章目录 9.1 HTML5 新增标签和属性9.1.1 基础知识9.1.2 案例 1&#xff1a;创建一个结构化的博客页面9.1.3 案例 2&#xff1a;使用新的表单元素创建事件注册表单9.1.4 案例 3&#xff1a;创建一个具有高级搜索功能的搜索表单 9.2 HTML5 表单增强9.2.1 基础知识9.2.2 案例 1&a…