IPC进程间通信探索——管道的原理与特点

  🤣 爆笑教程 👉 《看表情包学Linux》

🔥 CSDN 累计订阅量破千的火爆 C/C++ 教程的 2023 重制版,C 语言入门到实践的精品级趣味教程。
了解更多: 👉 "不太正经" 的专栏介绍 ← 试读第一章
订阅链接: 🔗《C语言趣味教程》 猛戳订阅!

目录

Ⅰ. 进程间通信(IPC)

0x00 引入:为什么要进程间通信?

0x01 进程间通信发展

Ⅱ. 管道(PIPE)

0x00 引入:何为管道?

0x01 匿名管道(Anonymous Pipe) 

0x02 管道通信的原理

0x03 管道通信的特点

0x04 系统调用:pipe 接口


Ⅰ. 进程间通信(IPC)

0x00 引入:为什么要进程间通信?

IPC(Inter-Process Communication,进程间通信

​在讲解进程间通信之前,我想我们应当首当其冲地去了解下:为什么要进程间通信?

进程间通信,难道是吃饱了撑了吗?进程喜欢没事聊两句?当然不是!

我们在之前讲过 "进程之间是具有独立性" 的,如果进程间想交互数据,成本会非常高!

因为独立性之本质即 "封闭",进程们你封闭你的我封闭我的,那么进程间的交流可谓是窒碍难行。

进程间的通信说白了就是 "数据交互",我们需要多进程进行协同处理一件事情。(宏观概念)

​刚才说的是宏观上的概念,下面我们来看看具体的、为什么要进行通信:

  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 资源共享:多个进程之间共享资源
  • 通知事件:一个进程需要向另一个或一组进程发送讯息,通知它 (它们) 发生了某种事件(比如进程终止时要通知父进程)
  • 进程控制:有些进程希望完全控制另一个进程的执行(如 debug 进程),此时控制进程希望能够拦截另一个进程的所有陷阱和异常,并能够及时知道它的状态改变,属于 "闭环控制"。

因此不要以为,进程独立了就是彻底独立,有时我们需要双方能够进行一定程序的信息交互。

0x01 进程间通信发展

​System V IPC 现在用的已经非常少了,更多的用于本地通信。

这已经是历史产物了,只讲共享内存共享内存什么的我们就不讲了,

因为现在大家都乐于谈论分布式,跨主机的东西了。

Ⅱ. 管道(PIPE)

0x00 引入:何为管道?

​ 鼠鼠我啊整天生活在下水道捏,在管道里阴暗地爬行,对管道可是非常熟悉的捏!

何为管道?管道是 \textrm{Unix} 系统中最古老的 IPC 形式,

将一个进程连接到另一个进程的数据流称为管道 (Pipe)。

​在 \textrm{Linux} 中,管道分为 匿名管道命名管道

下面我们先来讲解 匿名管道 (Anonymous Pipe) !

0x01 匿名管道(Anonymous Pipe) 

匿名管道是计算机进程间的一种 单工 先进先出通信机制,全双工通信 通常需要两个匿名管道。

💭 举个例子:假设内存中有两个独立的进程 A 和 B,我们想让 AB 之间进行进程间通信。

* 令 A 先把数据拷贝到磁盘上,再让 B 去读取该数据,如下图所示:

​我们可以通过这个例子明白一个道理:通信之前,要让不同的进程看到同一份资源。 

现阶段我们要学的进程间通信,不是如何通信,而是先去关注它们是如何看到同一份资源的。

那么在进程通信之前,如何做到让进程 "先看到同一份资源" 呢?

 资源的不同,决定了不同种类的通信方式! 而管道,就是提供共享资源的一种手段。

我们知道,文件在内存和磁盘之间来回切换是非常耗时的,因此进程间通信大多都是内存级别的。

​ 即在内存内部重建一块 "小区域" 进行通信,示意图如下:

对我们来说,我们 echo 一个 hello,写到文件中,实际上这就算通信了:

​但是我们要讨论的不是这种通信!我们讨论的是内存级的通信!

0x02 管道通信的原理

我们在前几章中学了文件描述符 (fd) 的知识点,我们将其系统中存在的匿名管道相结合:

首先,一个进程维护自己进程对应的文件描述符表 file_struct,而 file_struct 中有对应的数组。

​数字里存的是 struct file* fd_array[],这里面存的就是打开文件的文件指针。

其中 0,1,2 被默认占用,这个在之前我们也做过讲解,对应 stdin, stdout, stdin,这里不再赘述。

如果我们今天打开一个文件,OS 为了管理文件,需要将磁盘中的文件的属性信息加载到内存里。

​对该文件形成 struct file,包含了文件的所有属性,对应了文件的:

  • ① 操作方法 
  • ② file 自己内部的缓冲区

如果我们让该进程 fork 创建一个子进程,

在做拷贝时是不需要将 struct file 本身给子进程拷贝一份的。

创建子进程 task_struct file_struct 是需要被拷贝的,但是 struct file 是不需要的。

"创建进程,和我文件有什么关系?"

这也就是为什么我们创建 fork 子进程之后,让父子打印时,都会像同一个显示器打印的原因。

🔺 结论:struct file 一定能找到对应缓冲区的操作方法和 file 自己内部缓冲区。

0x03 管道通信的特点

我们来看看现实生活中的管道,管道大部分都是单向的,所有的管道都是为了传输资源的。

  • 现实中的管道:传输天然气和石油
  • 计算机中的管道:传输数据

在计算机通信领域的管道,如果文件不再是磁盘文件,通过特定的接口表征自己的身份。

自己读写数据时就在文件对应的内存缓冲区里完成数据交互,我们称该文件为 管道 (pipe) 。

Linux 下一切皆文件,因此管道也是文件,管道的底层就是基于 struct file 的。

进程间通信管道是单向的,传输数据的。单向的原因是因为管道的通信特点就是单向的。

❓ Q & A:

① 为什么父进程要分别打开读和写?因为为了让子进程继承,让子进程不用再打开了。
③ 为什么父子要关闭对应的读写?因为管道必须是单向通信的,这是操作系统决定的。
③ 谁决定,父子关闭什么读写?因为不是由管道本身决定的,是由你的需求决定的。

所以对我们来说,管道的建立就一定会出现打开两次文件,然后父子进程还要关闭 fd。

关闭我们 close 就行,但是打开还要我们 open 两次是不是未免太过于麻烦?不用担心!有 pipe!

0x04 系统调用:pipe 接口

Linux 给我们提供了 pipe 接口,只需调一下 pipe 就会在底层自动把文件以读和写的方式打开。

​ 你会得到两个 fd,并且会被写进 pipefd[2] 数组中:

#include <unistd.h>
int pipe(int pipefd[2]);   // 数组中分别存储第一次 O_RDONLY 和 O_WRONLY

你可以理解为:pipe 内部封装了 open,并且它 open 了两次:

  • 第一次 open:以 O_RDONLY 读的方式打开
  • 第二次 open:以 O_WRONLY 写的方式打开

最后,把读写 fd 分别放在 pipefd 数组的 0 下标和 1 下标中,这就帮你创建了一个共享文件。

并且别忘了 pipe 可是系统调用,创建文件时就在内核中将文件类型初始化 i_pipe

让它指向的是一个管道文件,指向管道信息,也就不用和磁盘产生关联了。

当父进程没有写入的时候,子进程在等,所以父进程写入之后,

子进程才能 read(会返回)到数据,子进程打印读取数据要以父进程的节奏为主。

❓ 思考:父进程和子进程读写的时候(向显示器写入也是文件),是有一定顺序性的。父子进程各自 printf 的时候,会有顺序吗?

💡 答案是不会。管道内部没有数据,reader 就必须阻塞等待(read),管道内部如果数据被写满,此时 writer 就必须阻塞等待(write),等管道有数据。

完全乱序的地方就是缺乏访问控制,管道内部自带访问控制机制。

我们可以使用 CreatePipe 来创建匿名管道,并使用 ReadFile 与 WriteFile 函数来对管道进行读写操作,其读写操作总是阻塞式的。

新建进程可继承管道句柄,读管道时收到一个:意味着管道的写端句柄已经关闭。

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.8.2
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

比特科技. Linux[EB/OL]. 2021[2021.8.31 

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

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

相关文章

深度学习之tensorboard可视化工具

(1)什么是tensorboard tensorboard是TensorFlow 的一个可视化工具包&#xff0c;提供机器学习实验所需的可视化和工具&#xff0c;该工具的功能如下&#xff1a; 跟踪和可视化指标&#xff0c;例如损失和精度可视化模型图&#xff08;操作和层&#xff09;查看权重、偏差或其…

【动态规划】子序列系列

文章目录 动态规划&#xff08;子序列系列&#xff09;1. 最长递增子序列2. 摆动序列3. 最长递增子序列的个数4. 最长数对链5. 最长定差子序列6. 最长的斐波那契子序列的长度7. 最长等差数列8. 等差数列划分 || - 子序列 动态规划&#xff08;子序列系列&#xff09; 1. 最长递…

mac电脑访问windows共享文件夹连接不上(设置445端口)

前提&#xff1a;首先需要保证mac和windows都在同一局域网内&#xff0c;如果不在肯定是连不上的&#xff0c;就不用往下看了。 事情是这样的&#xff0c;公司入职发了mac电脑&#xff0c;但是我是window重度用户&#xff0c;在折腾mac的过程中&#xff0c;有许多文件需要从wi…

Arcgis 分区统计majority参数统计问题

利用Arcgis 进行分区统计时&#xff0c;需要统计不同矢量区域中栅格数据的众数&#xff08;majority&#xff09;&#xff0c;出现无法统计majority参数问题解决 解决&#xff1a;利用copy raster工具&#xff0c;将原始栅格数据 64bit转为16bit

kotlin 编写一个简单的天气预报app(三)broadcast换成eventbus

使用eventbus替换broadcast 将从Broadcast切换到EventBus有以下几个好处&#xff1a; 解耦性&#xff1a;通过使用EventBus&#xff0c;您可以实现组件之间的解耦。传统的Broadcast机制需要发送方和接收方明确知道对方的存在&#xff0c;并且需要在代码中设置Intent过滤器和广…

springboot项目如何自动重启(使用Devtools检测修改并自动重启springboot)

1. 问题&#xff1a; 我们在项目开发阶段&#xff0c;可能经常会修改代码&#xff0c;修改完后就要重启Spring Boot。经常手动停止再启动&#xff0c;比较麻烦。 所以我们引入一个Spring Boot提供的开发工具&#xff1b; 只要源码或配置文件发生修改&#xff0c;Spring Boot应用…

4年测试工程师,常用功能测试点总结,“我“不再走弯路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 输入框测试 1、字…

如何把几个视频合并在一起?视频合并方法分享

当我们需要制作一个比较长的视频时&#xff0c;将多个视频进行合并可以使得整个过程更加高效。此外&#xff0c;合并视频还可以避免出现“剪辑断层”的情况&#xff0c;使得视频内容更加连贯&#xff0c;更加容易被观众理解和接受。再有&#xff0c;合并视频还可以减少视频文件…

原型链污染,nodejs逃逸例子

文章目录 原型链污染原型链污染原理原型链污染小例子 原型链污染题目解析第一题第二题 Nodejs沙箱逃逸方法一方法二 原型链污染 原型链污染原理 原型链 function test(){this.a test; } b new test;可以看到b在实例化为test对象以后&#xff0c;就可以输出test类中的属性a…

“数智新应用”不再是口号,看汽车、医药、制造企业如何突出重围?

近日&#xff0c;以“释放数智生产力”为主题的 Kyligence 用户大会在上海前滩香格里拉大酒店成功举行。大会包含上午的主论坛和下午的 4 场平行论坛&#xff0c;并举办了闭门会议、Open Day 等活动。来自金融、零售、制造、医药等行业的客户及合作伙伴带来了超过 23 场主题演讲…

记录--一个好用的轮子 turn.js 实现仿真翻书的效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 国际惯例&#xff0c;官网链接 官网传送门 Github地址 github上有几个demos例子&#xff0c;介绍了基础用法。 我参考官网的例子&#xff0c;写了一个demo示例 安装 turn.js 依赖 jquery 库&#xff0…

Redis Cluster 在Spring中遇到的问题

Redis集群配置可能会在运行时更改。可以添加新节点&#xff0c;可以更改特定插槽的主节点。还有可能因为master宕机或网络抖动等原因&#xff0c;引起了主从切换。 无法感知集群槽位变化 SpringBoot2.x 开始默认使用的 Redis 客户端由 Jedis 变成了 Lettuce&#xff0c;但是当…

2023.7月最新ORACLE考试通过|微思-ORACLE官方授权中心

微思-ORACLE官方授权培训中心 2022 ORACLE OCP考试战报https://blog.csdn.net/XMWS_IT/article/details/125866726?ops_request_misc%257B%2522request%255Fid%2522%253A%2522169089281916800182194373%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&r…

深度学习:BatchNorm、LayerNorm、InstanceNorm、GroupNorm和SwitchableNorm的理解

深度学习&#xff1a;BatchNorm、LayerNorm、InstanceNorm、GroupNorm和SwitchableNorm的理解 深度学习中的NormBatchNormLayerNormInstanceNormGroupNormSwitchableNorm 附录 深度学习中的Norm 在深度学习中会经常遇到BatchNorm、LayerNorm、InstanceNorm和GroupNorm&#xf…

振弦采集仪完整链条的岩土工程隧道安全监测

振弦采集仪完整链条的岩土工程隧道安全监测 隧道工程是一种特殊的地下工程&#xff0c;其建设过程及运行期间&#xff0c;都受到各种内外力的作用&#xff0c;如水压、地震、地质变形、交通荷载等&#xff0c;这些因素都会对隧道的安全性产生影响。因此&#xff0c;对隧道的安…

SpringBoot项目使用MyBatisX+Apifox IDEA 插件快速开发

今天跟大家介绍两个快速开发项目的插件。能大大提高开发效率。希望能帮助到大家。 1、MyBatisX 插件 MyBatis-Plus为我们提供了强大的mapper和service模板&#xff0c;能够大大的提高开发效率。但是在真正开发过程中&#xff0c;MyBatis-Plus并不能为我们解决所有问题&#xf…

AR开发平台 | 探索AR技术在建筑设计中的创新应用与挑战

随着AR技术的不断发展和普及&#xff0c;越来越多的建筑师开始探索AR技术在建筑设计中的应用。AR(增强现实)技术可以通过将虚拟信息叠加到现实场景中&#xff0c;为设计师提供更加直观、真实的建筑可视化效果&#xff0c;同时也可以为用户带来更加沉浸式的体验。 AR开发平台广…

Docker Compose 安装与使用(常用指令)

一、简介 Docker Compose 是一个编排多容器分布式部署的工具&#xff0c;提供命令集管理容器化应用的完整开发周期&#xff0c;包括服务构建、启动和停止。使用步骤&#xff1a;1. 利用 Dockerfile 定义运行环境镜像 2. 使用 docker-compose.yml 家义组成应用的各服务 3. 运行 …

IO进程线程day5(2023.8.2)

一、Xmind整理&#xff1a; 父进程会拷贝文件描述符表给子进程&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;①从终端获取一个文件的路径以及名字。②若该文件是目录文件&#xff0c;则将该文件下的所有文件的属性显示到终端&#xff0c;类似ls -l该文件夹③若该文…

【Linux命令200例】touch用来创建新的文件或者修改已有文件

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜…