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