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. linux下mysql数据库的学习

    转载博客:http://freedomljtt.blog.163.com/blog/static/72294949201210145441701/ ubuntu12.04 卸载和安装mysql 卸载m ...

  2. C++实现网格水印之调试笔记(二)

    整理了一下要实现的论文Watermarking 3D Polygonal Meshes in the Mesh Spectral Domain,步骤如下: 嵌入水印 à 提取水印 à 优化(网格细分) ...

  3. LeetCode题解——3Sum Closest

    题目: 给定一个数组,和一个指定的值,找出数组中3个数,它的和最接近这个指定值,并返回这个和. 解法: 和上一题找3个数的和为0一样,先排序再遍历,这一次不需要记录路径. 代码: class Solu ...

  4. (转载)OC学习篇之---类的定义

    之前已经介绍了OC中的一个程序HelloWorld,今天我们继续学习OC中类的相关知识. OC和C的最大区别就是具有了面向对象的功能,那么说到面向对象,就不得不说类这个概念了,如果学过Java的话,那 ...

  5. fedora 安装python mysql

    如果你服务器环境允许yum,安装MySQL-python模块就很简单了. 如果直接安装不行,先 安装MySQL-devel后正常运行 yum install mysql-devel yum insta ...

  6. mysql repair data 语句

    1. 这条语句主要是用来修复一个表中的数据 , 在另一个统计表中没有统计时,进行修改统计表的操作 update expert_count ec inner join ( select sum(e.EF ...

  7. 应用数据存储到sdcard上一定要规范,android4.4.2有新规范

    如果你的android设备有内部存储空间,即通常所说的机身存储(这就是指主要外部存储),那么你从外部插入SD卡就是一个二级外部存储设备. 最新的Android 4.4系统中,外置存储卡(SD卡)被称为 ...

  8. AVCaptureDevice LED闪光灯控制

    转载自:http://blog.csdn.net/cloudhsu/article/details/7202368 #import <AVFoundation/AVFoundation.h> ...

  9. 从 ALAsset 中取出属性

    #pragma mark - 从相册数组中取出所有的 图片数据 -(NSMutableArray *)getImageFromAlbumArray:(NSArray *)albumArr { NSMu ...

  10. Unity3D之Mecanim动画系统学习笔记(二):模型导入

    我们要在Unity3D中使用上模型和动画,需要经过下面几个阶段的制作,下面以一个人形的模型开发为准来介绍. 模型制作 模型建模(Modelling) 我们的美术在建模时一般会制作一个称为T-Pose( ...