1、什么是管道?(管道的概念)
2、为什么要有管道?(管道的重要性或意义)
3、如何建立进程间管道
1、什么是管道
—就像现实中的水管,水就像数据。(连接进程,相当于在进程间连接一个通路,用来传递信息)
—管道是一种半双工的通信方式
—数据只能单向流动,而且只能在具有共同祖先的进程间使用。
所谓半双工的模式
形象来说类似一个单刀双掷开关,有两个选择,但是二者是互斥的,当选择了一方另一方就失效。
而对于此处的管道,可以把它想成是管道的一端,一次只能调用一种功能读入或者写入,二者也是互斥的。
管道通信是消息传递的一种特殊方式,管道机制必须提供以下三方面的协调能力:互斥、同步和确定对方的存在。
2、为什么要有管道
当然这种好处也是要付出代价的,也有缺点,但是相比之下,这种途径的优点远远超出了其缺点。
Unix(从而Linux)向应用软件提供了一些进程间通信的手段,早期的Unix提供了:管道(pipe),信(signal),跟踪(trace)。
进程之间的通信,从物理上分,可以分为同主机的进程之间的通信和不同主机间的进程之间的通信。从通信内容方式上分,可以分为数据交互、同步通信、异步通信。
Linux系统进程之间的通信方式大致如下图所示
![](http://www.2cto.com/uploadfile/Collfiles/20141014/2014101409200236.png)
集合上述两种从物理和内容方式的划分,可以这样理解上图:
(1)同主机进程间数据交互机制:无名管道(PIPE)、有名管道(FIFO)、消息队列(Message Queue)和共享内存(Shared Memory)。
(2)同主机进程间同步通信机制:信号量(Semaphore)。
(3)同主机进程间异步通信机制:信号(Signal)。
(4)不同主机间进程数据交互机制:套接字(Socket)、远程调用RPC(Remote Procedure Call)。
管道通信
管道又可以分为无名管道和命名管道,两者的用途是不一样的。
无名管道PIPE:主要用于具有亲缘关系的进程之间的通信,无名管道的通信是单向的,只能由一段到另外一段;无名管道是临时性的,完成通信后将自动消失。一般采用先创建无名管道,再创建子进程,使子进程继承父进程的管道文件描述符,从而实现父子进程间的通信;在非亲缘关系管道之间,如果想利用无名管道进行通信,则需要借助另外的文件描述符传递机制。
有名管道FIFO:有名管道是一个实际存在的特殊文件,利用有名管道可以实现同主机任意进程之间的数据交互。
无名管道是一种特殊的文件,这就意味着你可以向操作文件一样操作无名管道,无名管道在内核中对应的是一段特殊的内存空间,这段内存空间由操作系统进行管理,对用户是不可见的,在用户空间的应用程序中只能通过系统调用来访问它。在这段内存空间中以循环队列的方式来临时存储一个进程发往另外一个进程的信息,并且在通信完成后就会自动释放相应的空间。
即无名管道主要用于具有亲缘关系的父子进程之间的通信,是临时性的,需要先创建管道,再创建子进程;管道都是单向的,若要实现双向通信,则需要两个管道。命名管道是实际存在的文件,使用前需要先打开,管道默认的read和write操作都是阻塞式的。3、如何建立进程间管道?
管道机制的主体是系统调用pipe(),但是由pipe()所建立的管道的两端都在同一个进程中,这样的管道起不到进程间通信的作用。所以必须在fork()的配合下,才能在父子进程间或者两个子进程之间建立起进程间的通信管道。
(1)进程A创建了一个管道,创建完成时代表管道两端的两个已打开文件都在进程A中。
(2)进程A通过frok()创建出进程B,在fork()的过程中进程A的打开文件表按原样复制到进程B中。
(3)进程A关闭管道的读端,而进程B关闭管道的写段。于是,管道的写段在进程A中而读端在进程B中,成为了父子进程之间的通信管道。
(4)进程A又通过frok()创建进程C,而后关闭其管道写段而与管道脱离关系,使得管道的写段在进程C中而读端在进程B中,成为两个兄弟进程之间的管道。
为了实现“命名管道”,在“普通文件”,“块设备文件”,“字符设备文件”之外,又设立了一种文件类型,称为FIFO文件。对这种文件的访问严格遵循“先进先出”的原则。这样就可以像在磁盘上建立一个文件一样建立一个命名管道,具体可以使用命令mknod来建立。
函数介绍:
¢int read(intfd, void *buf, int count);
—功能:从参数fd指定的读端读取管道数据到大小为count的缓存buf中,返回实际读取到的字节数。
—参数
¢fd:管道读端
¢buf:缓存区,保存读到的数据
¢count:读取字节数
•intwrite(intfd, void *buf, intcount);
•功能:向参数fd指定的写端从缓存buf中取出count个字节到管道中,返回值为实际写入的字节数。
•fd:管道写端
•buf:缓存区,将要写入管道的数据
•count:写入的字节数