进程间通信 (一)【管道通信(上)】

news2024/9/25 19:15:45

目录

  • 1. 概况
  • 2. 管道通信的原理
    • 2.1 初步理解
    • 2.2 深入理解

1. 概况

  • 是什么:两个及以上的进程实现数据层面的交互,称为进程间的通信。

    因为进程独立性的存在,所以一个进程无法直接访问另一个进程的数据,即便是父子进程,子进程也只能看到父进程所共享的代码和数据,一旦一方有数据写入行为,就会发生写时拷贝,所以进程通信的成本是比较高的。

  • 为什么:因为有通信的需求,所以多进程直接需要进行通信,场景可以有如下几种:

    • 进程间发送基本数据
    • 发送命令(让一个进程通过对另一个进程发送一些命令达到控制另一个进程的目的)
    • 协同工作
    • 通知进程(让 A 进程告知 B 进程某些事件发生,也可以是一个父进程只负责监听其所有子进程的,当条件满足时,通知唤醒子进程去协同工作等等)

  • 怎么办:

    • 进程间是互相独立的,又为了保证不打破进程之间的独立性,但又必须让不同的进程看到同一份 “资源”,这样才能够让进程间进行通信。
    • 这一份让不同进程都能访问的资源是一段特定形式的内存空间,一般由操作系统提供。而为什么这段资源不能由一方的进程提供呢?还是因为进程之间具有独立性,如果有一方提供,那么其它进程要访问该资源,就等价于访问这个进程的数据,这样就破坏了进程的独立性。因此由第三方提供最合适不过了。
    • 所以进程访问这段空间进行通信,本质就是访问操作系统。而进程代表着用户,操作系统又不允许用户直接访问它,因此该 “资源” 从创建 ---- 使用 ---- 释放,都只能通过系统调用接口来实现。
    • 操作系统为了进程间能够通信,并且不能破坏进程的独立性,必然要从底层设计、接口设计,都要由操作系统自己独立设计。而一般的操作系统,会有一个独立的通信模块,隶属于文件系统 ------ IPC通信模块。
    • 关于操作系统的通信模块,很多企业都在做,因此就会存在各种各样的通信方案,所以需要定制一套通信标准。因此进程间通信是有标准的,System V && POSIX。(因为通信有标准,所以不同品牌设备,不同的底层硬件也好,不同的操作系统之间,才能够进行通信,比如我的 windows 依旧可以给 mac 电脑的你发信息等等)
    • 除此之外,还有一种文件级别的通信,即管道通信。

2. 管道通信的原理

在这里插入图片描述

who 命令:查询当前连接主机的用户量
wc -l :统计行数量
这两个命令在将来运行起来都是一个进程,而管道的整体逻辑就是将 who 这个进程的输出信息写入管道文件,再由 wc 这个进程读取数据,然后做标准输出给用户层。

一个进程被创建,有 task_struct 内核数据结构,里面有一个 files_struct 结构体,结构体内存储了 struct file* fd_array[ ] 这样的文件描述符表,存储指向打开文件对象的指针,并且默认打开三个标准输入输出流。当我们打开一个文件,操作系统创建 struct file 对象,然后为该文件分配一个没有被使用的最小的文件描述符,将 struct file 的地址填到文件描述符表对应的下标处。

不仅如此,每个文件都有自己独立的 inode,提供一个用于各种底层设备读写的 file_operators 方法集,里面存储的是指向各个底层外设读写方法的函数指针,以此来实现一切皆文件的理念。接着,每个文件还要提供属于自己的文件页缓冲区。而不管是该文件是被创建于磁盘中,还是从磁盘中打开的,对文件做读写时,都需要先将文件的数据加载到内存中,然后再内存中做修改,修改完后再刷新回磁盘(只读取文件内容也需要先加载到内存中)。

  • 我们创建一个文件,但是该文件在磁盘中并不存在(按照以前对于文件系统的理解,打开文件如果不存在即在磁盘中创建,然后分配 inode 和数据块,修改位图结构等等),但是此刻我想要创建的这种文件,一样有 inode,有 file_operators 方法集,也有文件页缓冲区,但是就是不存在于磁盘中,能实现吗??

    能实现!这就是内存级别的文件,不与外设交互的文件,inode 里面的各种文件属性照常,只需要把方法集内原本指向外设读写的函数指针改为直接指向页缓冲区做读写,这样就跟外设没有任何关系了,也不需要往磁盘刷新数据之类的操作了。在操作系统内核中是存在很多诸如这样的内存级文件的。

2.1 初步理解

在这里插入图片描述

接着,当一个进程打开一个文件时,我在这个进程中创建出一个子进程,操作系统就需要以父进程为模板,为子进程创建一个 task_strcut、拷贝父进程的进程地址空间 和 页表等内核结构,包括父进程的 files_struct 结构体也同样要拷贝一份!说白了,这个 files_struct 代表的就是一个进程打开的文件的列表,也算是进程的一个数据结构,同时子进程也需要能够看到父进程的一切数据(在不发生写时拷贝的前提),父进程打开的所有文件也是一种数据,因此子进程需要看到父进程打开的各个文件,所以这个 files_struct 子进程同样会拷贝父进程的。

但是,父进程打开文件时,创建的各种文件对象 struct file,子进程则不拷贝这些文件对象。因为文件对象是文件管理模块的东西,进程是进程,文件是文件,不代表该文件是这个进程打开的,该文件就属于这个进程的了。文件与进程是操作系统两个模块来着的,文件不属于任何一个进程,往深一点说,文件是操作系统帮助进程打开的,因此操作系统才是文件的管理者,而非进程,文件与进程只是关联关系。所以既然该文件不属于进程,为什么子进程要拷贝呢?子进程想拷贝也无法拷贝,因为这不是父进程的东西。

所以既然子进程也拷贝了父进程的 files_struct,那么子进程的 files_struct 结构体也同样指向了父进程所打开的文件对象(三个标准输入输出流 以及 父进程单独打开的一个文件),而我们在概况进程通信时就说过,进程通信的本质前提就是要让不同的进程看到同一份 “资源”!那子进程的 files_struct 中的某一个文件描述符也指向父进程所打开的那个文件啊,这不就是父子进程看到同一份 “资源” 了吗?!

加上我们说的,创建一个文件但可以让它不存在于磁盘中,所以父子进程看到的这一同个文件,父进程往文件写入数据,子进程读取数据,这样不就可以使父子进程通信起来了吗?!

而我们上述说的这一切,就是管道的本质,管道就是一个内存级别的文件。

  • 现在父子进程的文件描述符表都指向了同一个文件,当一方正在对文件做读写操作时,另一方突然把文件关闭了,会影响到正在写入的进程吗,又或者影响对文件写入的这个操作吗??

    不影响,我们要知道,struct file 结构体里面是维护了一个引用计数 count 的,用于记录当前指向该文件的进程个数,所以当创建了子进程,多了一个进程指向该文件,那么 count + 1,当一方在关闭该文件的文件描述符,count - 1,但是只要 count ≠ \neq = 0,该文件的 struct file 对象以及文件的属性,内容等数据就不会被释放,因此不影响。

  • 哎哎哎,你上面说子进程是拷贝父进程的 file_struct 结构体,那我父进程要是打开文件时是以 r 权限打开的呢,那子进程拷贝下来的 file_struct,对该文件的权限不也是 r,大家都是 r,通信个屁啊。还怎么做到父进程写、子进程读,或者子进程写、父进程读这样的通信
    在这里插入图片描述

    但其实父进程在打开一个管道文件时,并不是只以 w / r 的方式打开的,而是同时打开以读和写的方式打开文件,之后父进程创建出来的子进程也同样的以读和写的方式指向该文件,再结合用户的实际需求,关闭一方的读或写端口,这样只有一方保持的一种状态,即可完成进程间的通信。

2.2 深入理解

在这里插入图片描述

因为要建立通信,所以父进程在打开一个文件时,不仅仅是以读或写的方式打开,父进程需要以两种方式打开文件,而对于该行为,操作系统会为同一个文件创建两个struct file,一个读方式,一个写方式,并且让进程中的文件描述符表分别指向读文件和写文件。而至于为什么操作系统要创建两个struct file,不直接将读写混为一个文件,可以理解为当读写都在一个文件进行时,父进程写完,子进程要读取时,文件内部的指针是指向父进程写入之后的位置,那么文件在做读取操作时,也是从文件指针往后开始读取,这样的话,子进程就读不出来父进程写的数据。当然,在技术实现上,这个问题并不能,可以将文件指针置为文件起始处,然后再进行读取,但这样就显得有些复杂麻烦了,有点简单问题复杂化的感觉,明明可以创建两个 struct file 搞定的事情,一定要频繁的移动文件指针。所以将读写文件分开,父进程写入时,由写文件的文件指针记录着位置,下次写入直接继续往后写入即可,子进程同理,读取到什么位置,都有一个文件指针维护着,这样既不互相干扰,何乐而不为呢?这也是操作系统的设计理念,可以用简单的方式解决问题,绝对不用复杂的方案。

不过虽然读写文件分开了,但因为这是属于同一个文件,文件属性,数据块都是相同的,因此这两个 struct file 都指向同一个文件缓冲区。接着,父进程创建子进程,子进程也以读写的方式各自指向这两个struct file 文件。

但是操作系统为了不让父子进程混淆各自的数据,即只让父子进程进行单向通信!单向通信即关闭父子进程其中一端文件操作,只让父子进程有读或写的一段。如果父子进程同时对文件的保留读写权限,那么父进程就既可以向文件写入,也可以读取,这样的话,父子进程就需要去确认哪些数据是自己写入的,哪些数据是从另一方进程读取过来的,这样又把简单问题复杂化了,因此操作系统在这件事上,只支持单向通信!如果确实有双向通信的需求,那么再重新建立一个管道文件,实现另一个方向的通信即可。

因为两个struct file 文件都指向的同一个页缓冲区,所以父子进程同时对这个缓冲区是可视状态的,而为了双方进程都互不干涉,互不影响,一般都会关闭该进程不使用的一端文件操作的权限,即如果父进程不使用读取端,指向struct file r 的文件描述符就会被关闭,子进程同理。

而上述这种基于文件级别的通信,就是管道通信的原理!但是,对于管道这个名字的由来,不要把因果关系搞反了,是因为这种通信是基于文件级别的 + 单向通信,因此才叫做管道,而不是它叫管道,所以它才是单向通信的。

  • 如果两个进程不具备父子关系,或者没有任何关系,能不能用管道文件的方式进行通信呢??

    如果两个进程不具备任何关系,那么答案是 不能! 如果两个进程具有血缘关系,那么是可以进行管道通信的。

    血缘关系就是父进程( A ) 的子进程( B ) 再创建了一个子进程( C ),那么这个 C 进程就是 A 进程的孙子进程,它是可以跟 A 和 B 进程进行通信,因为 C 进程中的 file_struct 是拷贝 B 进程的,B 进程中的 file_struct 是拷贝 A 进程的,因此它们都指向同一个 struct file,所以它们能进行通信;不仅如此,假如 A 再创建了一个子进程 B2,B2 也可以跟 A、B、C的任何一个进程通信,换言之,只要进程间具有血缘关系,那么就可以使用管道通信。

  • 匿名管道: 诸如上述这种内存级别的文件,它没有文件名,也没有路径,没有 inode 等文件属性信息,因为它不需要通过路径来定位该文件,它存在于内存中,它也不需要根据文件名 和 inode 来区分与其它文件的关系,因为这种文件只有父子进程这样具有血缘关系的进程才能够看到,诸如父子进程这样的进程也不用担心找不到该文件资源,这一份父子进程共同看到的 “资源”,是在进程创建时就被继承下来了,因此不需要任何文件信息,父子进程依旧能够看到这个 “资源”,而这种管道文件就称为 匿名管道

至此,两个进程还没有进行通信!你没听错,上述的一切,只是建立了通信信道,进程间并没有开始通信起来。这就是我们在概况中提到的,进程间具有独立性,因此进程间的通信是有成本的!


由于篇幅问题,关于管道是如何建立通信的,以及管道的应用场景,管道通信(下)

如果感觉该篇文章给你带来了收获,可以 点赞👍 + 收藏⭐️ + 关注➕ 支持一下!

感谢各位观看!

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

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

相关文章

数字IC设计\FPGA 职位经典笔试面试整理--基础篇2

1. 卡诺图 逻辑函数表达式可以使用其最小项相加来表示,用所有的最小项可以转换为卡诺图进行逻辑项化简 卡诺图讲解资料1 卡诺图讲解资料2 卡诺图讲解资料3 最小项的定义 一个函数的某个乘积项包含了函数的全部变量,其中每个变量都以原变量或反变量的形…

从传统到智能:低代码平台在生产型企业中的应用实践

在全球数字化浪潮的推动下,生产型企业正面临前所未有的变革压力。为了在激烈的市场竞争中保持竞争力,企业迫切需要通过技术手段实现业务流程的优化和创新。然而,传统的软件开发方式往往耗时耗力,难以快速响应市场需求。低代码平台…

一些依赖库的交叉编译步骤

交叉编译链版本:12.3.0 一、curl-7.43.0库交叉编译 libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传&a…

Django学习实战篇六(适合略有基础的新手小白学习)(从0开发项目)

前言: 上一章中,我们完成了页面样式的配置,让之前简陋的页面变得漂亮了些。 整理一下目前已经完成的系统,从界面上看,已经完成了以下页面: 首页分类列表页标签列表页口博文详情页 这离我们的需求还有些距离&#xff0…

哪款手机软件适合记事?记事本软件推荐

在这个信息爆炸的时代,手机已经成为我们生活中不可或缺的一部分。它不仅携带方便,而且功能强大,几乎可以完成我们日常所需的所有任务。随着生活节奏的加快,人们越来越需要一个可靠的工具来帮助自己记录重要信息和工作事项。这时候…

德勤校招网申笔试综合能力测试SHL题库与面试真题攻略

德勤的综合能力测试(General Ability)是其校园招聘在线测评的关键环节,旨在评估应聘者的多项认知能力。以下是对这部分内容的全面整合: 综合能力测试(General Ability) 测试时长为46分钟,包含…

ORA-12560:TNS:协议适配器错误

今天准备在数据库服务器创建一个用户,使用管理员账号进行登录 sqlplus / as sysdba时,突然报了个ORA-12560:TNS:协议适配器错误,吓的我一激灵,不应该啊,之前一直都是正常的,也是在网…

大漠yolo-数据集标注

参考 【按键精灵】大漠插件yolo环境配置_哔哩哔哩_bilibili 1. 2. 3.启动

MySQL高阶1873-计算特殊奖金

目录 题目 准备数据 分析数据 总结 题目 编写解决方案,计算每个雇员的奖金。如果一个雇员的 id 是 奇数 并且他的名字不是以 M 开头,那么他的奖金是他工资的 100% ,否则奖金为 0 。 返回的结果按照 employee_id 排序。 准备数据 Crea…

记录踩坑 uniapp 引入百度地图(微信小程序,H5,APP)

前言 因为公司要求一定要用百度地图,网上引入百度地图的方法说的就三种(插件,异步,webview组件),因为我用的是VUE3 第一种方法引入插件(插件名vue-baidu-map)一直报错vue2没试过反正vue3引进去就是报错第二种方法用异步引入 如果只开发app和h5可以用,微信小程序反正不显示,但…

android studio 批量修改包名 app package name

1、批量修改包名:project view模式 我们可以看到,只可以修改myapplication的部分包名,前面的com.demo这个修改了,可以进行如下设置来达到修改demo的目的。 2、设置下,通过不同的目录来达到批量修改的目的:…

2024最新甄选7款超好用的文档加密软件 | 好用的企业文档加密软件大盘点!赶快码住!

在数字化时代,文档如同古代的锦书密函,承载着企业的智慧与机密。 正如古诗所云:"锦书难托云中雁,密语常藏月下窗。" 2024年,我们不仅要传承古人的智慧,更要借助现代科技的力量,守护…

张朝阳的物理课第三卷:量子力学的硬核探索与启发

💂 个人网站:【 摸鱼游戏】【神级代码资源网站】【海拥导航】🤟 找工作,来万码优才:👉 #小程序://万码优才/HDQZJEQiCJb9cFi💅 想寻找共同学习交流,摸鱼划水的小伙伴,请点击【全栈技…

使用Prometheus进行系统监控,包括Mysql、Redis,并使用Grafana图形化表示

Prometheus是一个开源的的监控工具,而且还免费。这一次我们用Prometheus来对之前安装的所有服务,包括Mysql、Redis、系统状况等进行监控,并结合Grafana进行图形化展示 Prometheus下载和安装 下载地址(以下所有插件的官方下载地址…

二叉搜索树(来学包会) C++经验+1

目录 什么是二叉搜索树 解二叉搜索树 二叉搜索树的操作 二叉搜索树的插入(三步走) 二叉搜索树的搜索 二叉搜索树的删除 1.删除的节点是叶子节点 2.删除的节点只有一边的子树 3.删除的节点左子树和右子树都有 详细完整代码 什么是二叉搜索树 二…

MT76X8、MT7621、MT7981和QCA9531的GPIO列表

一、 MT76X8 GPIO列表; 二、 MT7621 GPIO列表; 三、MTK7981 GPIO列表; 四、QCA9531 GPIO列表;

CentOS 7 aarch64制作openssh 9.9p1 rpm包 —— 筑梦之路

本篇文章还是基于开源项目openssh-rpms制作。 https://github.com/boypt/openssh-rpms.git 官方发行说明: OpenSSH: Release Notes 1. 修改version.env 2. 下载源码包 openssl网站改版,下载地址和之前不一样了 # 下载openssl1.1.1w源码包cd downlo…

nacos 快速入门

目录 什么是 Nacos Nacos 的主要特点: Dockerfiledocker-compose.yml 快速搭建 nacos 单机 什么是 Nacos Nacos/nɑ:kəʊs/ 是“动态命名和配置服务”的缩写,是一个用于构建云原生应用的易于使用的动态服务发现、配置和服务管理平台。 Nacos 致力于…

【JAVA开源】基于Vue和SpringBoot的图书馆管理系统

本文项目编号 T 044 ,文末自助获取源码 \color{red}{T044,文末自助获取源码} T044,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

Linux·进程概念(上)

1.操作系统 任何计算机系统都包含一个基本的程序合集,称为操作系统(Operator System)。笼统的理解,操作系统包括: 内核(进程管理,内存管理,文件管理,驱动管理) 其他程序(函数库,shell程序) OS的…