FIFO有时被称为命名管道。管道只能由相关进程使用,这些相关进程的共同祖先进程创建了管道。但是,通过FIFO,不相关的进程也能交换数据

FIFO是一种文件类型(参考http://www.cnblogs.com/nufangrensheng/p/3501533.html)。stat结构(http://www.cnblogs.com/nufangrensheng/p/3501385.html)成员st_mode的编码指明文件是否是FIFO类型。可以用S_ISFIFO()宏对此进行测试。

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

#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
返回值:若成功则返回0,若出错则返回-1

mkfifo函数中mode参数的规格说明与open函数中的mode相同(见http://www.cnblogs.com/nufangrensheng/p/3497789.html,具体的mode取值见http://www.cnblogs.com/nufangrensheng/p/3505129.html)。新FIFO的用户和组的所有权规则与http://www.cnblogs.com/nufangrensheng/p/3502133.html中所述的相同。

一旦已经用mkfifo创建了一个FIFO,就可用open打开它。其实,一般的文件I/O函数(close、read、write、unlink等)都可用于FIFO。

应用程序可以用mknod函数创建FIFO。POSIX.1原先并没有包括mknod函数,它首先提出了mkfifo。mknod现在已包括在XSI扩展中。在大多数系统中,mkfifo调用mknod创建FIFO。

POSIX.1也包括了对mkfifo(1)命令的支持。于是,用一条shell命令就可以创建一个FIFO,然后用一般的shell I/O重定向对其进行访问。

当打开一个FIFO时,非阻塞标志(O_NONBLOCK)产生下列影响:

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

类似于管道,若用write写一个尚无进程为读而打开的FIFO,则产生信号SIGPIPE。若某个FIFO的最后一个写进程关闭了该FIFO,则将为该FIFO的读进程产生一个文件结束标志。

一个给定的FIFO有多个写进程是很常见的。这就意味着如果不希望多个进程所写的数据互相穿插,则需考虑原子写操作。正如对于管道一样,常量PIPE_BUF说明了可被原子地写到FIFO的最大数据量。

FIFO有下面两种用途:

(1)FIFO由shell命令使用以便将数据从一条管道线传送到另一条,为此无需创建中间临时文件。

(2)FIFO用于客户进程-服务器进程应用程序中,以在客户进程和服务器进程之间传送数据。

我们各用一个例子来说明这两种用途。

实例:用FIFO复制输出流

FIFO可被用于复制串行管道命令之间的输出流,于是也就不需要写数据到中间磁盘文件中(类似于使用管道以避免中间磁盘文件)。管道只能用于进程间的线性连接,然而,因为FIFO具有名字,所以它可用于非线性连接

考虑这样一个操作过程,它需要对一个经过过滤的输入流进行两次处理。图15-9表示了这种安排。

图15-9 对一个经过过滤的输入流进行两次处理

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

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

我们创建FIFO,然后在后台启动prog3,它从FIFO读数据。然后启动prog1,用tee将其输出发送到FIFO和prog2。图15-10显示了这种安排。

            图15-10 使用FIFO和tee将一个流发送到两个进程

实例:客户进程-服务器进程使用FIFO进行通信

FIFO的另一个应用是在客户进程和服务器进程之间传送数据。如果有一个服务器进程,它与很多客户进程有关,则每个客户进程都可将其请求写到一个该服务器进程创建的众所周知的FIFO中(“众所周知”的意思是:所有需要与服务器进程联系的客户进程都知道该FIFO的路径名)。图15-11显示了这种安排。因为对于该FIFO有多个写进程,客户进程发送给服务器进程的请求其长度要小于PIPE_BUF字节。这就能避免客户多个write之间的交错(http://www.cnblogs.com/nufangrensheng/p/3560130.html)。

   

     图15-11 客户进程用FIFO向服务器进程发送请求  

在这种类型的客户进程-服务器进程通信中使用FIFO的问题是:服务器进程如何将回答送回各个客户进程。不能使用单个FIFO,因为服务器进程会发出对各个客户进程请求的响应,而请求者却不可能知道什么时候去读才能恰如其分地读到对它的响应。一种解决方法是每个客户进程都在其请求中包含它的进程ID。然后服务器进程为每个客户进程创建一个FIFO,所使用的路径名是以客户进程的进程ID为基础的。例如,服务器进程可以用名字/tmp/serv1.XXXXX创建FIFO,其中XXXXX被替换成客户进程的进程ID。图15-12显示了这种安排。

        图15-12 客户进程-服务器进程用FIFO进行通信

这种安排可以工作,但也有一些不足之处。其中之一是服务器进程不能判断一个客户进程是否崩溃终止,这就使得客户进程专用的FIFO会遗留在文件系统中。另一个不足之处是服务器进程必须捕捉SIGPIPE信号,因为客户进程在发送一个请求后没有读取响应就可能终止,于是留下一个只有写进程(服务器进程)而无读进程的客户进程专用FIFO。

按照图15-12中的安排,如果服务器进程以只读方式打开众所周知的FIFO(因为它只需读该FIFO),则每当客户进程数从1变成0时,服务器进程就将在FIFO中读到一个文件结束标记。为使服务器进程免于处理这种情况,一种常用的技巧是使服务器进程以读-写方式打开其FIFO。

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

进程间通信之FIFO的更多相关文章

  1. linux 进程间通信 之fifo

    上一篇博客已经介绍了一种进程间通信的方式,但是那只是针对于有血缘关系的进程,即父子进程间的通信,那对于没有血缘关系的进程,那要怎么通信呢?  这就要创建一个有名管道,来解决无血缘关系的进程通信, fi ...

  2. 3.2 进程间通信之fifo

    一.引言 FIFO常被称为有名管道,不同于管道(pipe).pipe仅适用于“有血缘关系”的IPC.但FIFO还可以应用于不相关的进程的IPC.实际上,FIFO是Linux基础文件类型中的一种,是在读 ...

  3. 【APUE】进程间通信之FIFO

    FIFO也称为有名管道,它是一种文件类型,是半双工的.FIFO简单理解,就是它能把两个不相关的进程联系起来,FIFO就像一个公共通道,解决了不同进程之间的“代沟”.普通的无名管道只能让相关的进程进行沟 ...

  4. linux下的进程间通信概述

    管道(PIPE) FIFO(有名管道) XSI消息队列 XSI信号量 XSI共享内存 POSIX信号量 域套接字(Domain Socket) 信号(Signal) 互斥量(Mutex) 其中信号(s ...

  5. Python3 与 C# 并发编程之~进程先导篇

      在线预览:http://github.lesschina.com/python/base/concurrency/1.并发编程-进程先导篇.html Python3 与 C# 并发编程之- 进程篇 ...

  6. 20155339 《信息安全系统设计》第十周课下作业-IPC

    20155339 <信息安全系统设计>第十周课下作业-IPC 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在该进程的 ...

  7. 2017-2018-1 20155307 《信息安全系统设计基础》第十周课上未完成补充以及课下IPC作业

    课上内容2:stat命令的实现-mysate 学习使用stat(1),并用C语言实现 提交学习stat(1)的截图 man -k ,grep -r的使用 伪代码 产品代码 mystate.c,提交码云 ...

  8. Linux文件详解

    一.Linux文件类型分:普通文件.目录文件.链接文件.设备文件.管道文件. 1.普通文件:由ls -al显示属性时,第一个属性为 [-],例如 [-rwxrwxrwx].包括: 纯文本文件(ASCI ...

  9. Linux系统编程——进程间通信:命名管道(FIFO)

    命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...

随机推荐

  1. [King.yue]Ext.Net 正则表达式用法

    例: .Regex("^[A-Za-z0-9]+$")   //正则表达式 .InvalidText("只能输入英文字符和数字.")); //输入错误提示

  2. sql语句中获取datetime任何部分

    sql语句中获取datetime的日期部分 sql语句中 经常操作操作datetime类型数据.今天在写一个存储过程的时候需要将 一个datetime的值的 日期部分提取出来.网上有许多这方面的介绍. ...

  3. 【九度OJ】题目1009-二叉搜索树

    题目 思路 构建二叉搜索树,并保存先序遍历和中序遍历的序列在samplePreOrder,sampleInOrder 每遇到一个新的序列,构建一棵二叉搜索树,保存先序遍历和中序遍历的序列testPre ...

  4. JavaScript中的事件冒泡机制

    事件冒泡机制 事件冒泡发生的条件:当为多个嵌套的元素设置了相同的事件处理程序,它们将触发事件冒泡机制.在事件冒泡中,最内部的元素将首先触发其事件,然后是栈内的下一个元素触发该事件,以此类推,直到到达最 ...

  5. 五指CMS 3.0 手动升级方法

  6. trie树 Codeforces Round #367 D Vasiliy's Multiset

    // trie树 Codeforces Round #367 D Vasiliy's Multiset // 题意:给一个集合,初始有0,+表示添加元素,-去除元素,?询问集合里面与x异或最大的值 / ...

  7. SSHFS

    SSHFS(SSH文件系统) 是一个文件系统客户端程序,使用它可以将远程服务器上的目录挂载在本地直接访问 可以在网站http://igikorn.com/sshfs-windows-8/内下载

  8. 搭建nodejs环境推荐用两个工具:nvm和npm

    nvm 是 nodejs version manager 的简称,即:nodejs版本管理npm 是 nodejs package manager 的简称,即:nodejs模块管理 有了这两个工具,管 ...

  9. Codeforces Round #359 (Div. 2) C. Robbers' watch (暴力DFS)

    题目链接:http://codeforces.com/problemset/problem/686/C 给你n和m,问你有多少对(a, b) 满足0<=a <n 且 0 <=b &l ...

  10. UVaLive 6623 Battle for Silver (最大值,暴力)

    题意:给定一个图,让你找一个最大的子图,在这个子图中任何两点都有边相连,并且边不交叉,求这样子图中权值最大的是多少. 析:首先要知道的是,要想不交叉,那么最大的子图就是四个点,否则一定交叉,然后就暴力 ...