FIFO

来源:互联网 发布:法院淘宝拍卖流程图 编辑:程序博客网 时间:2024/04/27 19:50

FIFO有时被称为命名管道。未命名的管道只能在两个相关的进程之间使用,而且这两个相关的进程还要有一个共同的创建了它们的祖先进程。但是,通过FIFO,不相关的进程也能交换数据。

FIFO是一种文件类型。通过stat结构的st_mode成员的编码可以知道文件是否是FIFO类型。可以用S_ISFIFO宏对此进行测试。

创建FIFO类似于创建文件。FIFO的路径名存在于文件系统中。

#include <sys/stat.h>int mkfifo(const char *path, mode_t mode);int mkfifoat(int fd, const char *path, mode_t mode);           // 两个函数的返回值: 若成功,返回0; 若出错, 返回-1

mkfifoat 函数和mkfifo函数相似,但是mkfifoat函数可以用来在fd文件描述符表示的目录相关的位置创建一个FIFO。和其他*at函数一样,有三种情形:

(1)如果path参数指定的是绝对路径名,则fd参数会被忽略掉,并且mkfifoat函数的行为和mkfifo类似。
(2)如果path参数指定的是相对路径名,则fd参数是一个打开目录的有效文件描述符,路径名和目录有关。
(3)如果path参数指定的是相对路径名,并且fd参数有一个特殊值AT_FDCWD,则路径名以当前目录开始,mkfifoat和mkfifo类似。

当open一个FIFIO时,非阻塞标志(O_NONBLOCK)会产生下列影响

  • 在一般情况下(没有指定O_NONBLOCK),只读open要阻塞到某个其他进程为写而打开这个FIFO为止。类似地,只写open要阻塞到某个其他进程为读而打开它为止。
  • 如果指定了O_NONBLOCK,则只读open立即返回。但是, 如果没有进程为读而打开一个FIFO,那么只写open将返回-1,并将errno设置成ENXIO。

FIFO有以下两种用途 :

  1. shell命令使用FIFO将数据从一条管道传送到另一条时,无需创建中间临时文件。
  2. 客户进程-服务器进程应用程序中,FIFO用作汇聚点,在客户进程和服务器进程二者之间传递数据。

实例1: 用FIFO复制输出流
FIFO 可用于复制一系列shell命令中的输出流。这就防止了将数据写向中间磁盘文件,这点类似与使用管道来避免中间磁盘文件。但是,管道只能用于两个进程直接的线性连接,而FIFO是有名字的,因此它可用于非线性连接。
例如,需要对一个经过过滤的输入流进行两次处理,见下图:

这里写图片描述

使用FIFO和UNIX程序tee就可以实现这样的过程而无需使用临时文件。(tee程序将其标准输入同时复制到标准输出以及其命令行中命名的文件中)

mkfifo fifo1prog3 < fifo1 &prog1 < infile | tee fifo1 | prog2

创建FIFO,然后在后台启动prog3, 从FIFO读数据。然后启动prog1,用tee将其输出发送到FIFO 和 prog2。 图15-21显示了进程安排。
这里写图片描述

实例2: 使用FIFO进行客户进程-服务器进程通信
FIFO的另一个用途是在客户进程和服务器进程直接传送数据。如果有一个服务器进程,它与很多客户进程有关,每个客户进程都将其请求写到一个该服务器进程创建的众所周知的FIFO中。 图15-122显示了这种安排。
这里写图片描述

因为该FIFO有多个写进程,所以客户进程发送给服务器进程的请求的长度要小于PIPE_BUF字节。这样就能避免客户进程 的多次写之间的交叉。

在这种类型的客户进程-服务器进程通信中使用FIFO的问题是:
服务器进程如何将回答送回各个客户进程。不能使用单个FIFO,因为客户进程不可能知道何时去读它们的响应以及何时响应其他客户进程。一种解决方法是,每个客户进程都在其请求中包含它的进程ID。然后服务器进程为每个客户进程创建一个FIFO,所使用的路径名是以客户进程的进程ID 为基础的。例如服务器进程可以用名字/tmp/serv1.xxxxx创建FIFO,其中xxxxx被替换成客户进程的进程ID。图15-23显示了这种安排。
这里写图片描述

0 0
原创粉丝点击