Linux下进程通信 匿名管道pipe

匿名管道(pipe):

匿名管道(pipe)是Linux支持的最初Unix IPC形式之一

匿名管道进行父子进程之间通信需要用到的函数:
int pipe(int fildes[2]);
一般都是指创建匿名管道,其中传出 int fildes[2] 参数是固定的;
fildes[0] 代表读端,fildes[1] 代表写端。
适用于有血缘关系的进程。
通常父子进程之间是不要使用 sleep() 函数的,因为管道默认就是堵塞的
虽然实现形态上是文件,但是管道本身并不占用磁盘或者其他外部存储的空间。在Linux的实现上,它占用的是内存空间

20200329_165752.png

  • 本质:
    是内核缓冲区。也是伪文件(不占用磁盘空间)
  • 特点:
    • 其读端和写端,对应两个文件描述符;数据写端流入,读端流出
    • 操作管道的进程被销毁之后,管道自动被释放了
    • 管道默认是阻塞的(读写端)
  • 实现原理:
    • 内部实现方式:环形队列。只有一次读写的机会。先进先出。
    • 其缓冲区默认是 4K 大小;但是大小会随着实际情况适当 调整。
  • 局限性:
    • 队列:数据只能够读取一次,不能够重复读取
    • 半全工方式工作
      设置管道为非阻塞
      管道默认是阻塞的,那么如何设置管道为非阻塞的呢?
      通过下面代码给需要修改阻塞状态的文件描述符进行增加flag的操作。
int flags = fcntl(fd[0], F_GETFL);
flags |= O_NONBLOCK;
fcntl(fd[0], F_SETFL, flags);

2 匿名管道(pipe)

2.1 什么是匿名管道?

匿名管道(pipe)是Linux支持的最初Unix IPC形式之一,具有以下特点:

  • 匿名管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立两个管道;
  • 只能作用于父子进程或者兄弟进程之间(具有亲缘关系的进程)
  • 单独构成的一种独立的文件系统:匿名管道对于管道两端的进程而言,就是一个文件,但它不是普通文件,它不属于某种文件系统,而是自理门户,单独构成一种文件系统,去并且只存在于内存中。
  • 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓存区的头部读出数据。

2.2 匿名管道的实现机制

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


    5713484-1d562f8269b81345.png
  • 从原理上,匿名管道利用fork机制建立,从而让两个进程可以连接到同一个PIPE上。
    1. 最开始的时候,上面的两个箭头都连接到同一个进程Process 1上(连接在Process 1上的两个箭头)。
    1. 当fork复制进程的时候,会将这两个连接也复制到新的进程(Process 2)。
    1. 随后,每个进程关闭在自己不需要的一个连接(两个黑色的箭头被关闭;Process 1关闭从PIPE来的输入连接,Process 2关闭输出到PIPE的连接),这样,剩下的红色连接就构成了上图的PIPE。

5713484-cfdbad83904e2279.png

设想
通过pipe函数创建匿名管道之后。用fork函数进行子进程的创建。创建之后,在那一瞬间,父进程和子进程具有相同的文件描述符表。因此,在子进程中也存在一个文件描述符指向管道缓冲区。

关闭父进程的写端,关闭子进程的读端。就形成了下面的这个通信图。

20200708165132429.png

2.3 匿名管道实现细节

  • 在Linux中,匿名管道的实现并没有使用专门的数据结构,而是借助了文件系统的file结构,和VFS的索引节点inode。
  • 通过将两个file结构指向同一个临时的VFS节点,而这个VFS索引节点又指向了一个物理页面而实现的。
5713484-7d91e2fab54d6c95.png

2.4 关于匿名管道的读写

  • 匿名管道的实现的源代码在fs/pipe.c中,在pipe.c中有很多函数,其中有两个函数比较重要,即匿名管道pipe_read()读函数和匿名管道写函数pipe_write()。
  • 匿名管道写函数通过将字节复制到VFS索引节点指向物理内存而写入数据,而匿名管道读函数则通过复制物理内存而读出数据。
    当然,内核必须利用一定的同步机制对管道的访问,为此内核使用了等待队列、和信号
  • 当写入进程向匿名管道中写入时,它利用标准的库函数write(),系统根据库函数传递的文件描述符,可找到该文件的file结构。
  • file结构中制定了用来进行写操作的函数(即写入函数)地址,于是,内核调用该函数完成写操作。
  • 写入函数在向内存中写入数据之前,必须首先检查VFS索引节点中的信息,同时满足如下条件时,才能进行实际的内存复制工作
  • 内存中有足够的空间可以容纳所有要写入的数据。
  • 内存没有被读程序锁定。
  • 如果同时满足上述条件,写入函数首先会锁定内存,然后从写进程的地址空间中复制数据到内存。
  • 否则,写进程就休眠在VFS索引节点的等待队列中,接下来,内核将调用调度程序,而调度程序会选择其他进程运行。
  • 写进程实际处于可中断的等待状态,当内存中有足够的空间可以容纳写入数据,或内存被解锁时,读取进程会唤醒写入进程,这时,写入进程将接受到信号。当数据写入内存之后,内存被解锁,而所有休眠在索引节点的读取进程会被唤醒。
  • 进程可以在没有数据或者内存被锁定时立即返回错误信息,而不是阻塞该进程,这一来于文件或管道的打开模式。
  • 进程可以休眠在索引节点的等待队列中等待写入进程写入数据。当所有的进程完成了管道操作之后,管道的索引节点被丢弃,而共享数据页被释放。
  • VFS
    VFS(virtual File System/虚拟文件系统):是Linux文件系统对外的接口。任何要使用文件系统的程序都必须经由这层接口来使用它。它是采用标准的Unix系统调用读写位于不同物理介质上的不同文件系统。VFS是一个可以让open()、read()、write()等系统调用不用关系底层的存储介质和文件系统类型就可以工作的粘合层。在Linux中,VFS采用的是面向对象的编程方法。

参考

Linux中父子进程、兄弟子进程之间通信方式--匿名管道pipe(适用于有血缘关系的进程)
进程之间通信之匿名管道(PIPE)和有名管道(FIFO)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容