一、FIFO的概念:
匿名管道(pipe)的⼀个不⾜之处是没有名字,因此,只能⽤于具有亲缘关系的进程间通信;
因此,提出了命名管道;命名管道(FIFO) 提供⼀个路径名与之关联,以FIFO的⽂件形式存储于⽂件系统中。
命名管道是⼀个设备⽂件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。
值得注意的是, FIFO(first input first output)总是按照先进先出的原则⼯作,第⼀个被写⼊的数据将⾸先从管道中读出。
二、FIFO的创建和读写:
(1)指令创建命名管道:mknod或mkfifo命令
格式:mknod namedpipe
(2)调用系统函数创建命名管道:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo( const char *pathname, mode_t mode);
功能:
命名管道的创建。
参数:
pathname: 普通的路径名,也就是创建后 FIFO 的名字。
mode: 文件的权限,与打开普通文件的 open() 函数中的 mode 参数相同,相关说明请点此链接。
返回值:
成功:0
失败:如果文件已经存在,则会出错且返回 -1。
后期的操作,把这个命名管道当做普通文件一样进行操作:open()、write()、read()、close()。但是,和无名管道一样,操作命名管道肯定要考虑默认情况下其阻塞特性。
(3)打开命名管道
int fd = open( char name , int how);
name表示文件名字符串,
而how指定打开的模式:
O_RDONLY(只读),
O_WRONLY(只写),
O_RDWR (可读可写),
成功返回一个正整数称为文件描述符,
失败的话返回-1
注意:
调⽤open()打开命名管道的进程可能会被阻塞。
如果同时⽤读写⽅式(O_RDWR)打开,则⼀定不会导致阻塞;
如果以只读⽅式(O_RDONLY)打开,则调⽤open()函数的进程将会被阻塞直到有写⽅打开管道;
同样以写⽅式(O_WRONLY)打开
也会阻塞直到有读⽅式打开管道。
后两种阻塞总结为:只读等着只写,只写等着只读,只有两个都执行到,才会往下执行。
(4)一个简单的命名管道的例子:
结果:
三、FIFO的特点:
1.单向通信;
2.不局限于只有亲缘关系的进程间通信;命名管道是⼀个设备⽂件,存在于内存中,只要可以访问该路径,就能够通过FIFO相互通信。
3.生命周期—随内核(一直存在,直到用户自己删除);
4.命名管道对上层提供的服务叫流服务(面向字节流),与传输格式无关系;
5.命名管道自带同步机制;
四、对比匿名管道和命名管道
相同点:
两种管道都是单向通信(数据只能从管道的一端写入,从另一端读出)。
都自带同步机制。
都对上层提供的服务是流服务(面向字节流) —与传输格式无关 。
管道不是普通的文件,不属于某个文件系统,其只存在于内存中。
管道在内存中对应一个缓冲区。不同的系统其大小不一定相同。
写入管道中的数据遵循先入先出的规则。
从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据。
不同点:
匿名管道的存在周期—随进程(进程结束,匿名管道消失)
命名管道的存在周期—随内核(创建了以后一直存在,用户什么时候删除,什么时候不在)匿名管道只适用于具有亲缘关系的进程间通信(无名字)
命名管道适用于任何两个可以进程(有名字);
命名管道(FIFO)和无名管道(pipe)有一些特点是相同的,不一样的地方在于:
1、FIFO 在文件系统中作为一个特殊的文件而存在,但 FIFO 中的内容却存放在内存中。
2、当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。
3、FIFO 有名字,不相关的进程可以通过打开命名管道进行通信。