从程序14-2和程序14-3中可以总结出管道操作的一个流程。父进程中先使用pipe函数创建管道,在调用fork函数创建子进程,在父子进程中维护管道的数据流向。程序退出时及时关闭管道的两端,具体流程如图14-4所示。
图14-4 匿名管道的创建流程
管道操作的基本流程为:先创建一个管道,使用fork创建子进程, 在父子进程中关闭不需要的文件描述符使用管道通信,程序结束。由于这是一个比较规范也是比较常用的管道使用模式,所以在ANSI/ISO C中将以上操作定义在两个标准的库函数popen和pclose中,它们的函数原型是:
函数popen 的参数 command 是一个在shell中可运行的命令字符串的指针,参数mode 是一个字符指针,这个参数只有两种值可以使用,r或者w,分别表示popen函数的返回值是一个读打开文件指针,还是写打开文件指针。当函数失败时返回值为NULL,并设置出错变量errno。
popen函数先执行创建一个管道,然后调用fork函数创建子进程,紧接着执行一个exec函数调用, 调用/bin/sh –c来执行参数command中的命令字符串,然后函数返回一个标准的I/O文件指针。返回的文件指针类型与参数mode有关,如果参数mode是r则文件指针连接到command 命令的标准输出,如果是w则文件指针连接到command命令的标准输 入。为了关闭popen函数返回的文件指针,可以调用pclose函数。pclose函数的参数stream是一个popen打开的文件描述符,当函数失败返回–1。
下面实例演示了使用popen和pclose函数实现调用shell命令cat来打印一个文件到显示器的程序。程序中先使用popen函数为cat命令创建一条数据管道,并指定数据管道从cat命令的输出读出数据。在后续的代码中使用fgets函数读出数据,并将数据显示到标准输出中。