Linux 管道pipe的实现原理

转载

管道

管道是进程间通信的主要手段之一。一个管道实际上就是个只存在于内存中的文件,
对这个文件的操作要通过两个已经打开文件进行,它们分别代表管道的两端。
管道是一种特殊的文件,它不属于某一种文件系统,而是一种独立的文件系统,有其自己的数据结构。
根据管道的适用范围将其分为:无名管道和命名管道。

无名管道

主要用于父进程与子进程之间,或者两个兄弟进程之间。在linux系统中可以通过系统调用建立起一个单向的通信管道,且这种关系只能由父进程来建立。

命名管道

命名管道是建立在实际的磁盘介质或文件系统(而不是只存在于内存中)上有自己名字的文件,任何进程可以在任何时间通过文件名或路径名与该文件建立联系。为了实现命名管道,引入了一种新的文件类型——FIFO文件(遵循先进先出的原则)。
实现一个命名管道实际上就是实现一个FIFO文件。命名管道一旦建立,之后它的读、写以及关闭操作都与普通管道完全相同。虽然FIFO文件的inode节点在磁盘上,但是仅是一个节点而已,文件的数据还是存在于内存缓冲页面中,和普通管道相同。

管道实现机制

管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。
管道的一端连接一个进程的输出。这个进程会向管道中放入信息。
管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。
一个缓冲区不需要很大一般为4K大小,它被设计成为环形的数据结构,以便管道可以被循环利用。
当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。
当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。
当两个进程都终结的时候,管道也自动消失。

创建过程

clipboard.png

细节

在Linux中,管道的实现并没有使用专门的数据结构,而是借助了文件系统的file结构和VFS的索引节点inode。
通过将两个file结构指向同一个临时的 VFS 索引节点,而这个 VFS 索引节点又指向一个物理页面而实现的。
如下图有两个 file 数据结构,但它们定义文件操作例程地址是不同的,其中一个是向管道中写入数据的例程地址,
而另一个是从管道中读出数据的例程地址。
这样,用户程序的系统调用仍然是通常的文件操作,而内核却利用这种抽象机制实现了管道这一特殊操作。
clipboard.png

读写操作

管道实现的源代码在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,
即管道读函数pipe_read()和管道写函数pipe_wrtie()。
管道写函数通过将字节复制到 VFS 索引节点指向的物理内存而写入数据,而管道读函数则通过复制物理内存中的字节而读出数据。
当然,内核必须利用一定的机制同步对管道的访问,为此,内核使用了锁、等待队列和信号。

当写进程向管道中写入时,它利用标准的库函数write(),系统根据库函数传递的文件描述符,可找到该文件的 file 结构。
file 结构中指定了用来进行写操作的函数(即写入函数)地址,于是,内核调用该函数完成写操作。
写入函数在向内存中写入数据之前,必须首先检查 VFS 索引节点中的信息,同时满足如下条件时,才能进行实际的内存复制工作:

内存中有足够的空间可容纳所有要写入的数据;

内存没有被读程序锁定。

如果同时满足上述条件,写入函数首先锁定内存,然后从写进程的地址空间中复制数据到内存。
否则,写入进程就休眠在 VFS 索引节点的等待队列中,接下来,内核将调用调度程序,而调度程序会选择其他进程运行。
写入进程实际处于可中断的等待状态,当内存中有足够的空间可以容纳写入数据,
或内存被解锁时,读取进程会唤醒写入进程,这时,写入进程将接收到信号。
当数据写入内存之后,内存被解锁,而所有休眠在索引节点的读取进程会被唤醒。

管道的读取过程和写入过程类似。但是,进程可以在没有数据或内存被锁定时立即返回错误信息,而不是阻塞该进程,
这依赖于文件或管道的打开模式。反之,进程可以休眠在索引节点的等待队列中等待写入进程写入数据。
当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页也被释放


shiyang6017
计算机
155 声望
59 粉丝
0 条评论
推荐阅读
那些年动态库加载碰到的事er
那些年那些事 Static变量 更新so后 值不变 TODO load-load-unload core TODO 链接那点事 link So搜索路径 优先级 链接时参数-Wl,-rpath ldd *.so时,若存在路径unknown的依赖库,那么该参数在链接时,就是未配置...

shiyang60171阅读 1.6k

工具篇:iTerm与Zsh
iTerm2支持许多的主题配色,可以自己定义,也可以参考网上现成的主题配色。我个人比较喜欢draculatheme配色。支持item,vim,phpstorm , 下方存在主题官网路径,按照教程安装即可。

super白4阅读 4.7k

麒麟操作系统 (kylinos) 从入门到精通 - 常用软件安装 - 第三篇 常用软件安装(windows下的习惯)
本篇内容大部分从应用商店进行安装,部分通过官网下载,少部分通过命令行安装。1.原生应用1.1钉钉1.2飞书1.3 蓝信1.4 腾讯文档1.5 金山文档1.6 搜狗输入法(拼音)1.7 五笔输入法1.8 libreoffice官方也带了WPS,...

码上世界3阅读 7.5k评论 17

封面图
深入剖析容器网络和 iptables
Docker 能为我们提供很强大和灵活的网络能力,很大程度上要归功于与 iptables 的结合。在使用时,你可能没有太关注到 iptables 的作用,这是因为 Docker 已经帮我们自动完成了相关的配置。

张晋涛3阅读 1.3k

封面图
Metasploit实现木马生成、捆绑及免杀
在一次渗透测试的过程中,避免不了使用到社会工程学的方式来诱骗对方运行我们的木马或者点击我们准备好的恶意链接。木马的捆绑在社会工程学中是我们经常使用的手段,而为了躲避杀毒软件的查杀,我们又不得不对木...

白风之下1阅读 9k

麒麟操作系统 (kylinos) 从入门到精通 - 办公环境 - 第十三篇 字体安装与windows字体的利用
正常情况下,系统下的wps或libreoffice用到的字体都已默认安装。但有时候一些ttf字体或者microsoft office下一些字体需要安装。我们可以在安装好office、acrobat之后,将C:\windows\Fonts文件夹中的字体(我是win...

码上世界2阅读 3.9k

封面图
麒麟操作系统 (kylinos) 从入门到精通 - 影音娱乐- 第三十篇 利用PKS观看电视台(IPTV)直播
类别:笔记本型号:中国长城 UF712硬件平台:飞腾处理器(ArmV8 指令集)系统:银河麒麟操作系统 V10 SP1(2203) 关键词:信创,麒麟系统,linux,PKS,银河麒麟,飞腾,arm64,arm,湖南卫视,中央电视台,电视直播,iptv

码上世界1阅读 3.8k

封面图
155 声望
59 粉丝
宣传栏