13.6 命名管道 ~ FIFO

命名管道 (有用的特点): 由于它们出现在文件系统中,所以他们可以像平常的文件名一样在命令中使用。
在创建的FIFO文件用在程序设计中之前,我们先通过普通的文件命令来观察FIFO 文件的行为。
实验:访问FIFO文件(首先空文件:/tmp/my_fifo)
(1)首先,尝试读取这个(空的)FIFO文件:如下(第一行是空的,第二行是在写入了字符之后重新读取的结果)


读取文件

向文件写入数据

(2)我们可以将读取的数据放在后台执行,这样可以一次执行两个命令:


mac实验内容

linux实验内容

实验解析:
因为FIFO 中没有数据,所以cat和echo程序被阻塞了,cat等待数据的到来,而echo 等待其他进程读取数据。 (这个是在后台,在前台可能会被中断)
在上面的第三步中,cat进程一开始就在后台被阻塞了,当echo向它提供了一些数据后,cat命令读取这些数据并把他们打印到标准输出上,然后cat程序退出,不再等待更多的数据。
它没有阻塞是因为当第二个命令将数据放入FIFO 后,管道将被关闭,所以cat程序中的read调用返回0字节,表示已经到达文件尾。

说明:与通过pipe 调用创建管道的不同,FIFO 是以命名文件的形式存在,而不是打开的文件描述符,所以在对它进行读写操作之前必须先打开它。FIFO也用open 和close 函数打开和关闭,这与我们前面看到的对文件的操作一样,但它多了一些其他的功能。对FIFO 来说,传递给open 调用的是FIFO的路径名,而不是一个正常的文件。

(1)使用open打开FIFO 文件

打开FIFO的一个主题限制是:程序不能以O_RDWR模式(是什么???)打开FIFO文件进行读写操作,这样做的后果并未明确定义。但这个限制是有道理的,因为我们通常使用FIFO只是为了单向传递数据,所以没有必要使用O_RDWR模式。如果一个管道以读/写方式打开,进程就会从这个管道读回它自己的输出。 (这个模式应该是读写双向操作)不过命名管道应该是为了单向设计的(管道应该都是)
若是确实需要在程序之间双向传递数据,最好使用一对FIFO或管道,一个方向使用一个,或者(但并不常用)采用先关闭再重新打开FIFO的方法来明确的改变数据流的方向。
(本章后面讨论用FIFO 进行双向数据交换的问题)
PS: 管道应该都是用于程序之间单向传递数据。

打开FIFO 文件和打开普通文件的另一点区别是,对open_flag (open函数的第二个参数)的O_NONBLOCK选项的用法。使用这个选项不仅改变open调用的处理方式,还会改变对这次open调用返回的文件描述符进行的读写请求的处理方式。

O_RDONLY / O_WRONLY / O_NONBLOCK 标志共有4中合法的组合方式,

open(const char *path , O_RDONLY); open调用将阻塞,除非有一个进程以写方式打开同一个FIFO,否则它不会返回。(与前面的cat类似)
open(const char *path, O_RDONLY | O_NONBLOCK);
即使没有其他进程以写方式打开FIFO,这个open调用也将成功并立刻返回。
open(const char *path, O_WRONLY);
open调用将阻塞,知道有一个进程以读方式打开同一个FIFO 为止。
open(const char *path, O_WRONLY | O_NONBLOCK);
这个函数调用总是立刻返回,但如果没有进程以读方式打开FIFO文件,open调用将返回一个错误的-1并且FIFO 也不会被打开。如果确实有一个进程以读的方式打开FIFO文件,那么我们就可以通过它返回的文件描述符对这个FIFO 文件进行写操作。

注意: O_ONOBLOCK 分别搭配O_RDONLY 和 O_WRONLY 在效果上的不同,如果没有进程以读方式打开管道,非阻塞写方式的open调用将失败,单非阻塞读方式的open调用总是成功。close调用的行为并不受O_ONOBLOCK标志的影响。

下面的例子是通过使用带O_NONBLOCK 标志的open调用的行为来同步两个进程。(这里没有选择使用多个实例程序的做法,而只是使用一个测试程序fifo2.c ,通过给该程序传递不同的参数来观察FIFO的行为)
源码在github上,


代码截图

运行步骤1

(2)运行结果

实验解析:

这个 程序能够在命令上指定我们希望使用的O_RDONLY、O_WRONLY 和O_NONBLOCK的组合方式。它会把命令行参数与程序中的常量字符串进行比较,如果匹配,就(用 |= 操作符)设置相应的标志。程序用access 函数俩检查FIFO 文件是否存在,如果不存在就创建它。
(在这个程序中,一直到最后都么有删除这个FIFO 文件,因为我们没有办法知道是否有其他的程序正在使用它。)

(2)不带O_NONBLOCK 标志的O_RDONLY 和O_WRONLY

测试程序可以使用不同的组合,注意:我们将第一陈旭(读取者)放在后台运行;


运行结果

这个可能是命名管道最常用的方法了,它允许启动读进程,并在open调用中等待,当第二程序打开FIFO文件时,两个程序继续运行。注意:读进程和写进程在open调用处取得同步。

注意:当一个Linux进程被阻塞时,它并不消耗CPU资源,所以这种进程的同步方式对CPU来说是非常有效的。

(3) 带O_NONBLOCK标志的O_RDONLY和不带盖标志的O_WRONLY

读进程执行open调用并立刻继续执行,及时没有写进程的存在。随后写程序开始执行,它也在执行open调用后立刻继续执行,但这次因为FIFO已被读进程打开。


看到并不会等待一定输入

这个过程和上面是有区别的

(4) 对FIFO进行读写操作

使用O_NONBLOCK模式会影响到FIFO的read和write调用。
对一个空的、阻塞的FIFO (即没有用O_NONBLOCK标志打开)的read调用将等待,知道有数据可以读时才执行。与此相反,对一个空的,非阻塞的FIFO 的read调用将立刻返回0字节。
对于一个完全阻塞的FIFO的write调用将等待,知道有数据可以被写入时才继续执行。如果FIFO不能接收所有写入的数据,它将按下面的规则执行。

  • 如果请求写入的数据的长度小于等于PIPE_BUF字节,调用失败,数据不能写入。
    *如果请求写入的数据的长度大于PIPE_BUF字节,将写入部分数据,返回实际吸入的字节数,返回值也可能是0.
    FIFO 的长度是需要考虑的一个很重要的因素。系统对任意时刻在一个FIFO中可以存在的而数据长度是有限制的。它由#define PIPE_BUF 语句定义,通常可以在头文件limits.h 中找到他。在Linux和许多其他类UNIX 系统中,它的值通常是4096 字节,但在某些系统中他可能会小到512 字节。系统规定:在一个以O_WRONLY 方式(即阻塞方式)打开的FIFO 中,如果写入的数据长度小于等于PIPE_BUF,那么或者写入全部字节,或者一个字节都不写入。
    虽然,对只有一个FIFO写进程和一个FIFO读进程的简单情况来说,这个显示并不是非常重要,但只使用一个FIFO并允许多个不同的程序向一个FIFO 读继承发送请求的情况很常见的。如果几个不同的程序尝试同时向FIFO写数据,能否拨正来自不同陈旭的数据块不相互交错就非常关键了。也就是每个写操作都必须是“原子化”,如果达到这一点?
    如果能够保证所有的写请求是发往一个阻塞的FIFO的,并且每个写请求的 数据长度小于等于PIPE_BUF字节,系统就可以确保数据决不会交错在一起。通常静每次通过FIFO传递的数据长度限制为PIPE_BUF 字节是个好方法,除非你只使用了一个写继承和一个读进程。

使用FIFO实现进程间通讯。

(管道中的进程通讯是在亲缘的进程之间进行通讯)
命名管道可以在没有亲缘关系的命名管道进行通信的,我们需要用到两个独立的程序;
【分别是fifo3.c(生产者) 、fifo4.c(消费者)】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容