[2.1.4]进程管理——进程通信
文章目录
- 第二章 进程管理
- 进程通信(IPC)
- 为什么进程通信需要操作系统支持?
- (一)共享存储
- (1)基于存储区的共享
- (2)基于数据结构的共享
 
- (二)消息传递
- 什么叫“格式化的消息”?
- (1)直接通信方式
- (2)间接通信方式
 
- (三)管道通信
 
- 小结
 
第二章 进程管理
进程通信(IPC)
这个小节我们会学习进程通信的几种方式,分别是
- 共享存储
- 基于数据结构的共享
- 基于存储区的共享
- 消息传递
- 直接通信方式
- 间接通信方式
- 管道通信
进程之间的通信(Inter-Process Communication, IPC)是指两个进程之间产生数据交互。
在一个系统当中,同时会有多个进程正在运行,那么这些进程之间难免需要相互配合着工作,在这种情况下,进程和进程之间的数据通信就显得很有必要了。
比如正在浏览微博的时候,可以通过分享功能,把一条微博分享给微信好友。这时就发生进程间的通信了。本来那条微博的链接是在微博里面的,直接就分享到微信里面了,这个过程显然是进程和进程之间发生了数据交互、发生了通信 。
既然进程之间的通信是很有必要的,那么该怎样实现进程之间的通信呢?这个需要操作系统的支持。
为什么进程通信需要操作系统支持?
为什么进程之间的通信一定要有操作系统内核的支持,原因是这样的。
我们系统中给各个进程分配内存地址空间的时候,各个进程的内存地址空间是相互独立的,比如进程P它可以访问自己的空间,进程Q可以访问自己的空间。但是进程P不可以访问进程Q的地址空间。
这么规定,是出于安全的考虑。因为,如果一个进程可以随意地访问其他进程的内存地址空间,那么一个进程就可以随意修改其他进程的数据了,或者随意读取其他进程的数据。那这样的话,试想一下,比如你的手机里面不知什么时候安装了一个垃圾软件,这个垃圾软件,如果它可以随意地访问其他进程的地址空间,那有可能它直接把你微信里的私密的一些聊天数据,或者照片之类的,直接读取走了。这显然是不安全的。

因此,出于安全考虑,各个进程只能访问自己的这片内存地址空间,而不能访问其他进程的内存地址空间,无论是读、写,都不行。
因此,如果P和Q,它们之间想要进行数据交互,想要进行进程之间的通信,那么显然,进程P是不可能直接把这个数据写到Q的这片空间里面的。
所以,由于进程不可直接访问其他进程的内存地址空间,因此就必须要有操作系统的支持才可以完成进程之间的通信。
接下来会介绍三种进程之间的通信方式:共享存储、消息传递、管道通信。
(一)共享存储
(1)基于存储区的共享
各个进程只能访问自己的这片空间,但是如果操作系统支持共享存储的功能,那么一个进程,它可以申请一片共享存储区。而这片共享存储区,也可以被其他进程所共享。

这样的话,一个进程P,如果它要给Q传送数据的话,那么P就可以先把数据写到这片共享存储区里面,因为P对共享存储区是有访问权限的。接下来进程Q再从共享存储区里面读出数据。
由于共享存储区可以被多个进程所共享,因此这些数据之间的数据交换,就可以通过这一片被共享的区域来进行。这就是共享存储的进程间通信方式。
比如Linux中,如何实现共享内存:
int shm_open(...); //通过shm_open系统调用,申请一片共享内存区
void * mmap(...); //通过mmap系统调用,将共享内存区映射到进程自己的地址空间(注:什么叫内存区映射,这是第三章内容。通过“增加页表项/段表项”,即可将同一片共享内存区映射到各个进程的地址空间中。)
另外,还需要注意一个问题,如果多个进程都往这片区域写数据的话,有可能会导致写冲突,会导致数据覆盖的问题。所以,各个进程之间如果使用共享存储的方式来进行通信的话,那么需要保证各个进程对这个共享存储区的访问是互斥的。也就是当进程P正在访问这片区域的时候,那其他进程就不能访问这片区域。
怎么实现这个互斥的功能呢?
操作系统内核会提供一些同步互斥工具(比如在后面会学习的P、V操作),各个进程从而能够对共享存储区实现一种互斥的访问。
刚才我们说的这种共享存储的方案,是基于存储区的共享。操作系统给你划定了这么大的一片区域,之后,若干个进程,到底是想往这片区域里的哪个位置写,或者从哪个位置读,这些都是很自由的。操作系统只负责把这片区域划给你,但是并不管你怎么使用这片区域。

基于存储区的共享:操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由参与通信的进程自己控制,而不是操作系统。这种共享方式速度更快,是一种高级通信方式。
(2)基于数据结构的共享
相比之下,还有一种基于数据结构的共享。
操作系统给你们两个进程,划定的共享区域,它就规定,只能存放一个长度为10的数组。这样的话,各个进程之间的通信自由度就没那么高,并且传送数据的速度也会比较慢。

基于数据结构的共享:比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信方式。
(二)消息传递
如果采用这种通信方式,那么进程之间的数据交换会以格式化的消息(Message)为单位。通过操作系统提供的“发送消息/接收消息”两个原语来进行数据交换。
什么叫“格式化的消息”?
所谓格式化的消息,由两个部分组成:消息头、消息体。
消息头,要写明注明,这个消息是由谁发送的,到底要发送给谁,整个消息的长度是多少,等等这些概要性的信息。
消息体,就是具体的,一个进程想要传送给另一个进程的数据。

这种消息传递的通信方式,又可以进一步划分为:直接通信方式、间接通信方式。
其中,直接通信方式就是,发送进程要指明接收进程的ID。(系统里每一个进程都会有一个ID,叫PID)直接通信方式的意思就是,我发送的时候,直接点明,就是要它接收。
而间接通信方式,会通过一个叫作“信箱”的中间实体来进行通信。所以间接通信方式又称为“信箱通信方式”。
(1)直接通信方式
进程P现在要给进程Q发送一个消息,而在操作系统的内核区域是管理着各个进程的PCB的。
  同时,会有各个进程PCB对应的消息队列。比如进程Q就有一个进程Q的消息队列,也就是其他进程要发送给进程Q、应该被进程Q接收的这些消息,都挂在这个队列里面。

  现在,进程P要给进程Q发送一个消息。首先,每个进程自己是有自己的地盘、自己的内存空间的,它会在此先完善这个消息的信息(如图msg),包括消息头、消息体。接下来,进程P会使用到发送原语send(Q, msg)(操作系统提供的发送原语),用它来指明,我的这个消息msg,是要发送给Q这个进程。

这个发送原语,会导致操作系统内核接收到这个消息,并且会把它 挂到进程Q的消息队列里面。
  此时,这个消息msg由进程P的内存空间,复制到了内核空间当中。

  接下来,进程Q通过接收原语receive(P, &msg),来指明现在要接收一个消息,是P发来的。此时,操作系统会检查进程Q的消息队列,看一下这几个消息到底哪一个是由P发送过来的。

找到了由P发送过来的消息,那么操作系统内核会把这个消息体的数据,又从操作系统的内核区复制到进程Q的用户区、地址空间。

消息传递——直接通信方式:点名道姓的消息传递。我在发送的时候,指明要发送给谁;我在接收的时候,指明要接收谁发来的消息。
(2)间接通信方式
刚才我们说过,间接通信方式,它需要一个中间实体(所谓的“信箱”)来进行消息的传递(所以又称之为信箱通信方式)。
这种通信方式是这样来实现的:
进程P和进程Q想要进行通信。那么进程P可以通过系统调用,申请一个信箱,当然也可以申请多个邮箱。比如此处,进程P申请了信箱A、信箱B。

现在,这两个进程怎么进行通信呢?
  首先,进程P在自己的地址空间里完善消息msg的内容,然后进程P可以使用发送原语send(A, msg),往信箱A发送消息msg。

间接通信方式,是指明了我要发送到哪个信箱,并没有指明我要发送给哪个进程。
那,进程Q在使用接收原语的时候,它可以指明,我要从信箱A中接收一个消息体。这样,信箱A中的这一个msg,就会被操作系统复制到进程Q的空间中了。

这就是使用信箱来完成消息传递的过程。
通常来说,操作系统是可以允许多个进程往同一个信箱里send消息,也可以多个进程从同一个邮箱里receive消息。
(三)管道通信

“管道”这个词还是很形象的,它就像一个水管、管道一样。就是,写进程可以从管道的一边写入数据,读进程从管道的另一边取走数据。
这个数据的流动只能是单向的。从左到右,或者从右到左,就像一根水管里的水流一样,不可以是双向同时进行的。
这里的管道,其实是一种特殊的共享文件,又名pipe文件。也就是,如果两个进程要用管道的方式进行进程通信,那么首先我们需要系统调用的方式,来申请一个管道文件,操作系统会新建这个管道文件。这个文件的本质就是在内存当中开辟了一个大小固定的内存缓冲区。然后,两个进程可以往这个内存缓冲区里面写数据和读数据,但是这个数据的读写是先进先出的(FIFO)。
问题:说到这里,管道通信是为两个进程开辟了一块内存缓冲区,而刚才所说的共享存储,也是开辟了一块共享存储区,也是可以被进程P、Q共享访问的。那么它们有什么区别?
区别是这样的:
刚才我们讲的基于存储区的共享,进程P、Q对于共享存储区中,具体的存储、读取位置,没有任何限制,很自由。但是,管道通信的方式,其中是一个数据流的形式,如果前边有空位,则写数据的时候要先往前边写,前边占满了再接着往后边区域写;读数据的时候也一样,只能先把前边的数据读空了,才可以读后边的这些数据,先进先出。

所以,管道通信和共享存储通信,区别还是很大的,管道通信的读写一定是先进先出的,可以把它理解为一个循环队列;而共享存储的读写是没有任何限制的。
1、管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信(全双工通信),则需要设置两个管道。

2、各进程要互斥地访问管道。(由操作系统实现)
3、刚才已经介绍到,这个管道是一个大小固定的内存缓冲区,因此会被写满。当管道写满时,写进程将阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
4、另一个方面,当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
5、(这一点,是很多教材最有争议的一个地方)管道通信的方式就决定了,一旦管道中的数据被读出,那就彻底消失了。所以,如果有多个读进程在读同一个管道的时候,就有可能导致错乱:因为我们管道里面的数据,它并没有指明我到底是要给进程Q的、还是要给进程R的。所以,如果多个进程都从同一个管道这读数据的话,那么就有可能这个数据的读取动作是比较乱的:第一块数据被Q读走了、第二块数据被R读走了。
针对这一问题,不同的操作系统会有不同的解决方案:①一个管道允许多个写进程,一个读进程(2014年408真题高教社官方答案);②允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux的方案)。
有的操作系统是①的方案,有的操作系统是②的方案。因此,有的教材按照①来说,管道允许多个写进程、但只允许一个读进程;而有的教材按照②来说,一个管道允许多个写进程、多个读进程。
对于408考试来说,按照①来说即可。但是从现实应用的角度来看,①②都是存在的。
小结

共享存储、消息传递、管道通信这三种常见的进程间通信方式。这三种通信的功能都是需要操作系统的底层来支持的。
共享存储,会设置一块共享内存区,并映射到进程的虚拟地址空间(这个问题在学完第三章,段表、页表之后再回来看就懂了,这个很简单)。
另外,各个进程对共享空间的访问要互斥地进行,这个互斥的效果是由进程自己进行控制的,如使用P、V操作来实现。实际上,对于共享存储区的互斥访问,是一个经典的同步互斥问题:读者、写者问题(在后面会讲)。
消息传递分为两种通信方式。直接通信方式就是要指名道姓地指明我要把消息发给哪个进程,然后操作系统会把这个消息直接挂到接收进程的消息队列里面。
间接通信方式又叫信箱通信,操作系统会把消息放到指定的信箱当中,而消息的接收者也需要指明自己从哪个信箱当中取走消息。
管道通信。对于操作系统而言,管道通信的这个管道,是一个特殊的共享文件(比如你在Linux系统上是的确能够找到这一文件的),但本质上这个文件就是一个内存缓冲区,如果结合数据结构的知识来看的话,这个内存缓冲区其实就是一个循环队列。那么,如果管道写满了,写进程就会被阻塞;如果管道读空了,读进程就会被阻塞。
此外,一个管道文件只能实现半双工通信。这类似于现实生活中的一根水管,同一时刻,水不可能既从左往右流、又从右往左流。
所以,如果想要从左往右、从右往左的水流同时存在的话,我可以建立两个管道,实现双向同时通信。
读进程想要从管道读数据,只需保证一点:管道不是空的,即可。至于管道是否写满、还是只写了一部分,都无所谓,只要不是空的就能读。
写进程同理,只要管道没满,还有空间让我可以写,就可以往管道中写数据。至于管道是完全空了、还是有一部分数据,都无所谓,只要不满就能写。
相关文章:
 
[2.1.4]进程管理——进程通信
文章目录第二章 进程管理进程通信(IPC)为什么进程通信需要操作系统支持?(一)共享存储(1)基于存储区的共享(2)基于数据结构的共享(二)消息传递什么…...
 
ChatGPT也有犯晕的时候
前面测试 ChatGPT 进行写代码、优化代码、解释代码、一般问答都表现的很好。偷个懒,用ChatGPT 帮我写段生物信息代码如果 ChatGPT 给出的的代码不太完善,如何请他一步步改好?代码看不懂?ChatGPT 帮你解释,详细到爆&…...
 
机器学习与目标检测作业:连通块算法
机器学习与目标检测作业:连通块算法一、连通块算法题目描述二、连通块算法文件结构三、连通块算法程序编写3.1、连通块算法conBlock.h头文件内容3.2、conBlock.cpp源文件内容3.3.3、mian.h头文件内容3.3.4、main.cpp源文件内容如下四、连通块算法程序运行结果一、连…...
HBase基础 --- 增删查改
目录 创建表 查看指定表全名空间中的表 查看表描述 禁用/启用 查看禁用/启动状态 删除表 新增列族 删除列族 更改列族存储版本的限制 增加数据 根据条件查询 查看指定列中不同版本的数据 删除指定列族下的指定列 删除指定行 全表扫描 全表扫描指定列族…...
 
如何基于AI智能视频技术实现公园景区的人流量实时统计?
一、方案背景春暖花开的季节来临,外出旅游的人群也越来越多。无论是景区、公园、博物馆、步行街等场所,客流超载非常大,给游客带来的体验较差,同时也存在安全隐患。当前景区面临的管理痛点包括:客流信息查询难…...
 
【JavaWeb】Servlet详解
文章目录1. 前置知识2.servlet生命周期2.1 默认情况下,服务器启动时,servlet对象并没有被创建2.2 用户执行一次请求2.3用户执行第二次请求2.4 3,4,5,6....次请求2.5 关闭服务器3.servlet方法解析4.适配器模式改造servlet4.1不使用servlet模式4.2使用适配…...
 
谁是世界上最好的编程语言?--编程语言70年浅谈
1、编程语言发展史纵览 严谨起见,本文提到的编程语言指的是「第三代高级编程语言」。 首先,我们从时间维度入手聊聊编程语言。一图胜千言,我们从目前主流的编程语言中,挑选出流行的、具有历史影响力的语言。把它们按时间从上往下…...
 
Webpack前端资源加载/打包工具
文章目录一、Webpack1、什么是Webpack2、Webpack安装2.1全局安装2.2安装后查看版本号3、创建项目3.1初始化项目3.2创建src文件夹3.3 src下创建common.js3.4 src下创建utils.js3.5 src下创建main.js4、JS打包4.1创建配置文件4.2执行编译命令4.3创建入口页面4.4测试5、CSS打包5.1…...
 
springcloud3 fegin实现服务调用1
一 Fegin的作用 1.1 fegin的作用 fegin是一个声明式的web服务客户端,让编写web服务器客户端变得非常容易,只需创建一个接口并在接口中添加FeginClients注解即可。 Fegin的使用方式:使用fegin的注解定义接口,调用这个接口&#…...
 
专业版即将支持自定义场景测试
物联网 MQTT 测试云服务 XMeter Cloud 专业版于 2022 年底上线后,已有不少用户试用,对数千甚至上万规模的 MQTT 并发连接和消息吞吐场景进行测试。同时我们也收到了希望支持更多物联网协议测试的需求反馈。 新年伊始,XMeter 团队全力聚焦于 …...
 
Process Monitor工具使用实验(23)
实验目的 学习Process Monitor实用小工具的使用,学会利用Process Monitor工具观察程序进程/线程、文件系统、注册表、网络连接等的活动。预备知识 Process Monitor是一个Windows系统下先进的监视工具,它可以显示文件系统、注册表、网络连接、进程…...
 
钓鱼客服到拿下服务器全过程(重点在于钓鱼添加img src)
重点总结 钓鱼时主动在变量中添加了字段,等待用户点击获取ip信息进行下一步资金盘plus呢 左看右看没啥东西,看看客服系统能不能打xss。 吊毛客服居然不在线,这套客服系统见过是whisper,之前审计过没有存储xss 但能通过伪造图片…...
 
【C++】list迭代器的深度剖析及模拟实现(感受类封装,类和对象的思想)
早点睡兄弟,别一天到晚就熬夜。 文章目录一、通过list迭代器来感受类和对象以及类封装的思想1.迭代器的特征和本质是什么?(两大特征:类的内嵌类型,行为像指针。本质:内置类型定义的变量或自定义类型实例化…...
 
JavaScript 语句、注释和代码块实例集合
文章目录JavaScript 语句、注释和代码块实例集合JavaScript 语句JavaScript 代码块JavaScript 单行注释JavaScript 多行注释使用单行注释来防止执行使用多行注释来防止执行JavaScript 语句、注释和代码块实例集合 JavaScript 语句 源码 <!DOCTYPE html> <html> &…...
 
华为机试题:HJ103 Redraiment的走法(python)
文章目录(1)题目描述(2)Python3实现(3)知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…...
 
html+css 实现 熊猫样式
效果 html代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible"…...
 
Vue基础19之插槽
Vue基础19插槽不使用插槽App.vueCategory.vue默认插槽:slotApp.vueCategory.vue具名插槽App.vueCategory.vue作用域插槽App.vueCategory.vue总结插槽 不使用插槽 App.vue <template><div class"bg"><Category :listData"food"…...
 
[Gin]框架底层实现理解(一)
前言:路由原理———压缩字典 这边简单讲一下gin非常重要的一个基点,也就是他作为go web框架的一个亮点 也就是Trie树和压缩字典算法 gin 通过树来存储路由,讲路由的字符拆解为一个个的结点,在获取handler函数时,会…...
 
css3横向无限公告消息滚动功能
html部分 {{item}}css部分 .boxingeds{ display: flex; flex-wrap: wrap; width: 150%; position: relative; left: 1000rpx; padding: 30rpx 0; position: absolute; top: 23%; z-index: 2; -webkit-animation: myfirst 30s linear 2s infinite; .textname{ display: inlin…...
 
【Git】Git工作流程及使用
Git工作流程及使用Git工作流程与常用命令Git工作流程Git常用命令项目中使用Git的场景需求开发前的分支拉取流程,需求开发后的分支合并流程分支合并出现冲突如何解决线上出现事故代码如何回退Git工作流程与常用命令 Git工作流程 workspace:工作区 stagin…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
 
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
 
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
 
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
 
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
 
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
 
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
