一、参考
二、什么是管道
管道是在父进程和子进程之间通信的机制,因为进程拥有各自独立的虚拟地址空间,所
以任意进程无法直接访问其他进程拥有的数据。为了实现进程间的通信,设计了管道。
管道对文件系统的一部分进行了巧妙的应用,使得进程间的通信成为可能,管道首先获取根磁盘的inode, 然后利用该inode指向的存储区进行数据交换。这个文件(inode和存储区域)构成了管道的实体。管道的容量由PIPSIZE
定义于ken/pipe.c
利用管道进行的通信过程如下:
(1)发送发的进程向管道写入数据,直到管道被充满;
(2)切换到接收方的进程,使得从管道读入数据,已经接收的数据从管道中被删除;
(3)数据全部读取后,切换到发送发的进程,返回(1)的处理
发送方以与管道相对应的inode[]
元素的地址+1, 接收方以该地址+2为参数执行sleep()
使用管道的优点:
在进程间传递数据也可以通过临时文件来实现,与临时文件相比,使用管道的优点:
(1)可使用的块设备的资源是有限的,管道的容量为固定的4096
字节,因此,即使用来交换更大容量的数据也不会占用更多的块设备区域,而使用临时文件时候,会占用与所交换的数据相等容量的块设备区域
(2)管道所需要的缓冲区的容量小于缓冲区的总容量,利于发挥块设备缓冲区的缓存功能,而且,当发送方的进程将数据写入管道后,接收方的进程将马上进行读取,块设备的缓存效果会更加明显,当使用临时文件时候,如果需要输出大于设备缓冲区容量的文件,缓冲区所带来的缓存效果将因此受到影响;
但是,当使用管道,且执行进程由发送方切换到接收方时候,如果存在执行优先级更高的进程,且该进程也使用了块设备的缓冲区的时候,则无法期待缓冲区带来的缓存效果。此时,虽然性能没有得到改善,但是由于数据已经输出到块设备,因此对通信内容本身不会造成影响。
管道基于现有的文件系统,实现的成本较低,尽管占用的资源较少,但是却实现了进程之间的高速通信,低投入高产出可以视为管道最大的魅力。
三、开始管道通信
系统调用pipe
用来建立管道通信,pipe()
是系统调用的处理函数
首先在user.u_ofile[]
和file[]
中分配供read
和write
使用的元素,然后获取根磁盘的inode[]
元素,将供read
和write
使用的file[]
元素指向该inode[]
元素,为file[]
元素设置表示管道的FPIPE
标志位
read
和write
使用的文件描述符返还给用户程序,用户程序对该文件描述符,可以像对待一般文件一样进行读写,实现管道通信。
四、收发数据
对通过系统调用pipe
取得的文件描述符,可以像对待一般文件那样执行系统调用read
和write
,从而实现数据收发
当设置了file[]
元素的FPIPE
标志位时候,在rdwr()
方法中执行writep()
和readp()
方法
4.1 writep
writep()
用于对管道进行写入处理,因为管道的实体为文件,所以采用与对待一般文件相同的方式调用writei()
写入数据,当管道被充满(4096
字节)时候进入睡眠状态,如果存在等待管道被写入数据的进程,则将其唤醒;但是,和一般文件处理不同,文件偏移量file.f_offset
不会发生变化
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。