管道

2015-02-17 19:23:48   最后更新: 2015-02-20 19:15:01   访问数量:1258




管道是 UNIX 系统 IPC 的最古老形式,所有的 UNIX 系统都支持这种通信机制,所以也是最常用的 IPC 形式

最简单的管道应用的例子就是:

ps aux | awk '{print $2}' | grep 'ngxin'

 

但管道有以下两个局限性:

  1. 管道是半双工的,虽然大部分系统已经经由域套接字支持了全双工管道和命名全双工管道,但是 linux 系统知识采取可选包方式提供支持
  2. 只能在具有公共祖先的进程之间使用

 

通常管道都是有一个进程创建,然后通过 fork 使父子进程通过该管道通信,如下图所示:

 

 

一个管道通常只有一个读进程与一个写进程

如果写一个读端已经关闭的管道,则会产生 SIGPIPE 信号,write 函数返回 -1,errno 被置为 EPIPE

在写管道(或 FIFO)时,常量 PIPE_BUF 规定了内核中管道缓冲区的大小,可以通过 pathconf 或 fpathconf 函数确定 PIPE_BUF 的值

 

具体使用的例子可以参考:

超轻量服务器 tinyhttpd 源码解析

在这个超轻量服务器中,主进程 fork 出 cgi 执行程序,就是通过管道接收 cgi 进程的输出的

 

int pipe(int filedes[2]);

 

调用成功返回 0,否则返回 -1

 

参数 filedes 用于返回

filedes[0] 用于读取管道中数据

filedes[1] 用于将数据写入管道

 

使用 fstat 函数对管道的每一端检测(使用 S_ISFIFO 宏),会发现返回的是 FIFO 类型的文件描述符

 

函数说明

标准IO库提供了管道的创建和销毁的函数

FILE *popen(const char *cmdstring, const char *type); int pclose(FILE *fp);

 

定义于 stdio.h

popen 返回创建的文件指针,如果调用失败返回空指针

返回 cmdstring 的终止状态,出错返回 -1

 

函数作用

函数 popen 先执行 fork,然后调用 exec 执行 cmdstring 保存的命令,并且返回一个标准 IO 文件指针

 

如果 type 参数为 "r",则文件指针连接到 cmdstring 的标准输出,如下图所示

 

如果 type 参数为 "w",则文件指针连接到 cmdstring 的标准输入,如下图所示

 

 

使用 popen 和 pclose 可以减少需要编写的代码量

 

在具体的编程环境中,常常使用一种程序设计的方式,即某个进程向另一个进程的标准输入写入数据,同时又接收该进程的标准输出,则这里所说的“另一个”进程就是一个“协同进程”

典型的是在 http 服务器中,服务器 fork 子进程执行 cgi 程序,通过 cgi 程序的标准输入向他写入调用参数,并且通过 cgi 程序写入标准输出的数据返回调用主进程

可以参考 tinyhttpd 的源码:

超轻量服务器 tinyhttpd 源码解析

在这个例子中,进程创建了两个管道,一个是协同进程的标准输入,一个是协同进程的标准输出,然后 fork 出 cgi 进程,并通过这两个管道与 cgi 进程通信

 

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      进程间通信      fork      ipc      pipe      子进程      父进程     


京ICP备15018585号