一、管道的概念
管道是一种队列类型的数据结构,它的数据从一端输入,另一端输出。管道最常见的应用是连接两个进程的输入输出,即把一个进程的输出编程另一个进程的输入。shell中存在专门的管道运算符"|",例如shell命令:
ps -ef |grep init
命令"ps -ef"分析当前运行的全部进程,并将结果打印到屏幕上。进程"grep init"从输入的字符串中查找包含字符"init"的子串,并打印结果。这两个领命通过管道符连接起来后就成了一个新的应用:查找正在应用的、命名中包含字符"init"的进程。
二、无名管道
无名管道通畅直接称之为管道,它占用两个文件描述符,不能被非血缘关系的进程共享,一般应用在父子进程中。
1.无名管道的建立
UNIX中一切皆为文件,管道也是文件的一种,成为管道文件。当系统创建一个管道时,它返回两个文件描述符:一个文件以只写打开,作为管道的输入端;另一个文件以只读打开,作为管道的输出端。
在UNIX中,采用函数pipe创建无名管道,其原型为:
#include<unistd.h>
int pipe(int fildes[2]);/*其中fildes[0]为读而开,fildes[1]为写而开,fildes[1]的输出是fildes[0]的输入*/
函数pipe在内核中创建一个管道,并分配两个文件描述符标识管道的两端,这两个文件描述符存储于fildes[0]和fildes[1]中。一般约定fildes[0]为输入端,进程向此文件描述符写入数据,fildes[1]描述管道的输出端,进程向此文件描述符中读取数据。函数pipe调用成功时返回0,否则返回-1。
2.单向管道流模型
管道的两端(输入和输出端)被一个进程控制没有太大的意义,如果管道的两端分别控制在不通的进程中,这两个进程之间就能够进行通信。拥有管道输入端的进程,可以向管道发送信息,拥有管道输出端的进程,可以从管道中接收一个进程发送来的信息。
1)从父进程流向子进程的管道
在父进程创建无名管道并产生子进程后,父子进程均拥有管道两端的访问权。此时关闭父进程的管道输出端、关闭子进程的管道输入端,就形成一个从父进程到子进程的管道流,数据由父进程写入、从子进程读出。创建从父进程流向子进程的管道过程如下:
1st:创建管道,返回无名管道的两个文件描述符fildes[0]和fildes[1]。
int fildes[2];
pipe(fildes);
2nd:创建子进程,子进程继续无名管道文件描述符。
3rd:父进程关闭管道的输出端,即关闭只读文件描述符fildes[0]。
close(fildes[0]);
4th:子进程关闭管道的输入端,即关闭只写文件描述符fildes[1]。
close(fildes[1]);
2)从子进程流行父进程的管道
在父进程创建无名管道并产生子进程后,父子进程均拥有管道两端的访问权。此时关闭父进程的管道输入端、关闭子进程的管道输出端,就形成一个从子进程到父进程的管道流,数据由子进程写入,从父进程读出。创立从子进程流向父进程的管道过程如下:
1st:创建管道,返回无名管道的两个文件描述符fildes[0]和fildes[1];
2nd:创建子进程,子进程中继续无名管道文件描述符。
3rd:父进程关闭管道的输入端,即关闭只读文件描述符fildes[1];
4th:子进程关闭管道的输出端,即关闭只写文件描述符fildes[0];
ex:一个管道的例子:父进程向管道写入一行字符,子进程读取数据并打印到屏幕上。