linux管道通信的优点,进程通信----管道(pipe)

Linux管道的实现机制

在Linux中,管道是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为:

·      限制管道的大小。实际上,管道是一个固定大小的缓冲区。在Linux中,该缓冲区的大小为1页,即4K字节,使得它的大小不象文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,当这种情况发生时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。

·      读取进程也可能工作得比写进程快。当所有当前进程数据已被读取时,管道变空。当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。

注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。

1. 管道的结构

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

a64d888190160000625f92c61d678aa0.png

两个 file 数据结构,但它们定义文件操作例程地址是不同的,其中一个是向管道中写入数据的例程地址,而另一个是从管道中读出数据的例程地址。这样,用户程序的系统调用仍然是通常的文件操作,而内核却利用这种抽象机制实现了管道这一特殊操作。

2.管道的读写

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

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

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

·内存没有被读程序锁定。

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

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

因为管道的实现涉及很多文件的操作

获取Linux 内存页(基页)大小的命令:getconf PAGE_SIZE ,一般的输出是4096,即 4KB。

11ecf0ff80f6ff3f9c2c2b0552bc14b0.png

管道的容量

f890c4c012f8446ce5041d6688421601.png

5a0b27bf5dfad339529b47069ed8fb7c.png

59545a7d50186c7fc64bade353622f9f.png

cc18d7d4cc6d61fa7fbbb86280983daf.png

【64KB】

管道的特点:

1 依赖文件系统

2 单向通信,要想双向,需要创建两个管道

3 允许有血缘关系的进程进行通信

4 面向字节流

5 管道随进程,进程在管道在,进程消失管道对应的端口关闭,两个进程都消失则管道消失。

管道的四种特殊情况:

情况1: pipe写端关闭  读端一直读 ,直到剩余数据都读完,最后一次read返回0,就像读到文件末尾一样。

测试代码:

dcad0d6ec6f2572a652c4cb293c3b38e.png

db07f08fd9332334b22c5a0e2d07c287.png

f5ab96a37c7cc5c97b8f6721ab6c9e5e.png

情况2:写端没有关闭,但写端也不写入数据,读端一直读,读完数据后再次read会阻塞,直到有数据时再读。

70d415677ee4afc931ee22fbcb91b128.png

情况3:读端关闭,写端write,那么进程会收到信号SIGPIPE,通常导致进程 异常终止

fa2288fc38be6be9a7e46283173dd068.png

77afd1cc936cf7f3a4739e508528db04.png

情况4:读端没有关闭,读端也没有读

写端一直写,管道被写满时再write会阻塞,直到管道中有空位置了才写入。

2031cf4dc806b494340ed0deaef209d6.png

e0b0f60d5303510fe3cd38089fc208d7.png

阻塞:

f289e1b2f4b3f122454594b6d3f344de.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值