进程间通信之FIFO
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的更多相关文章
- linux 进程间通信 之fifo
上一篇博客已经介绍了一种进程间通信的方式,但是那只是针对于有血缘关系的进程,即父子进程间的通信,那对于没有血缘关系的进程,那要怎么通信呢? 这就要创建一个有名管道,来解决无血缘关系的进程通信, fi ...
- 3.2 进程间通信之fifo
一.引言 FIFO常被称为有名管道,不同于管道(pipe).pipe仅适用于“有血缘关系”的IPC.但FIFO还可以应用于不相关的进程的IPC.实际上,FIFO是Linux基础文件类型中的一种,是在读 ...
- 【APUE】进程间通信之FIFO
FIFO也称为有名管道,它是一种文件类型,是半双工的.FIFO简单理解,就是它能把两个不相关的进程联系起来,FIFO就像一个公共通道,解决了不同进程之间的“代沟”.普通的无名管道只能让相关的进程进行沟 ...
- linux下的进程间通信概述
管道(PIPE) FIFO(有名管道) XSI消息队列 XSI信号量 XSI共享内存 POSIX信号量 域套接字(Domain Socket) 信号(Signal) 互斥量(Mutex) 其中信号(s ...
- Python3 与 C# 并发编程之~进程先导篇
在线预览:http://github.lesschina.com/python/base/concurrency/1.并发编程-进程先导篇.html Python3 与 C# 并发编程之- 进程篇 ...
- 20155339 《信息安全系统设计》第十周课下作业-IPC
20155339 <信息安全系统设计>第十周课下作业-IPC 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在该进程的 ...
- 2017-2018-1 20155307 《信息安全系统设计基础》第十周课上未完成补充以及课下IPC作业
课上内容2:stat命令的实现-mysate 学习使用stat(1),并用C语言实现 提交学习stat(1)的截图 man -k ,grep -r的使用 伪代码 产品代码 mystate.c,提交码云 ...
- Linux文件详解
一.Linux文件类型分:普通文件.目录文件.链接文件.设备文件.管道文件. 1.普通文件:由ls -al显示属性时,第一个属性为 [-],例如 [-rwxrwxrwx].包括: 纯文本文件(ASCI ...
- Linux系统编程——进程间通信:命名管道(FIFO)
命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...
随机推荐
- 关于Windows 7的64位系统不兼容某些控件的问题
我的问题是vsflex7.ocx 不能在64位系统下运行,导致软件的一个涉及到这个控件的功能出错.如下: 解决的办法基本思路是把这个控件注册一下.然后就可以了.就是这个控件: 目录中没有自己下载个. ...
- 关于CCSprite改变box2d刚体位置以及角度。
同事今天在讨论一个事情,box2d中,body不可以直接设置位置,这样是不合理的,因为在物理的世界,你去左右它的物理检测.它就没有存在的必要了.但是,有人就想直接用box2d的碰撞.不用物理模拟.怎么 ...
- 数往知来C#面向对象准备〈二〉
面向对象(OOP→Object-Oriented Programming) 1.什么是面向对象? 一种分析问题的方式. 2.面向对象三大特征: 封装(隐蔽代码实现/复用/修改方便).继承.多态. 3. ...
- java BigInteger类的用法
import java.math.BigInteger; Scanner in = new Scanner(System.in); BigInteger x1 = new BigInteger(&qu ...
- hadoop2.7【单节点】单机、伪分布、分布式安装指导
问题导读 1.从本文部署实际部署,总结本地模式.伪分布.分布式的区别是什么?2.单机是否是伪分布?3.本地模式是否可以运行mapreduce? 来源:about云 http://www.aboutyu ...
- hadoop HDFS 写入吞吐量
最近一个项目 在大把大把的使用hadoop-HDFS,关于HDFS 的优势网上都快说烂了,这里不再说了,免得被.. 呵呵 废话少说,开整 1.场景描述: 服务器A 监听 服务器B分发任务socket. ...
- 第二百三十七天 how can I 坚持
最近好像迷上看小说了,<灵域>,而且也感觉会看小说了. 话说,今天好冷啊,真怕在路上冻着就冻萌了,寒风赤骨啊. 好想买个帽子.好想让送个帽子. 睡觉.
- Delphi使用FindClass实现动态建立对像(有点像反射)
相关资料:http://www.blogjava.net/nokiaguy/archive/2008/05/10/199739.html { http://www.blogjava.net/nokia ...
- HDU 5752 Sqrt Bo (数论)
Sqrt Bo 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5752 Description Let's define the function f ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...