Linux 还支持另外一种管道形式,称为命名管道,或 FIFO,这是因为这种管道的操作方式基于“先进先出”原理。上面讲述的管道类型也被称为“匿名管道”。命名管道中,首先写入管道的数据是首先被读出的数据。匿名管道是临时对象,而 FIFO 则是文件系统的真正实体,如果进程有足够的权限就可以使用 FIFO。FIFO 和匿名管道的数据结构以及操作极其类似,二者的主要区别在于,FIFO 在使用之前就已经存在,用户可打开或关闭 FIFO;而匿名管道只在操作时存在,因而是临时对象。
为了创建先进先出文件,可以从shell提示符使用mknod命令或可以在程序中使用mknod()系统调用。
mknod()系统调用的原型为:
#include <sys/type.h>
#inlcude <sys/state.h>
#include <fcntl.h>
#include <unistd.h>
int mknod(char *pathname,node_t mode, dev_t dev);
其中pathname是被创建的文件名称,mode表示将在该文件上设置的权限位和将被创建的文件类型(在此情况下为S_IFIFO),dev是当创建设备特殊文件时使用的一个值。因此,对于先进先出文件它的值为0。
一旦先进先出文件已经被创建,它可以由任何具有适当权限的进程利用标准的open()系统调用加以访问。当用open()调用打开时,一个先进先出文件和一个匿名管道具有同样的基本功能。即当管道是空的时候,read()调用被阻塞。当管道是满的时候,write()等待被阻塞,并且当用fcntl()设置O_NONBLOCK标志时,将引起read()调用和write()调用立即返回。在它们已被阻塞的情况下,带有一个EAGAIN错误信息。
由于命名管道可以被很多无关系的进程同时访问,那么,在有多个读进程和/或多个写进程的应用中使用FIFO是非常有用的。
多个进程写一个管道会出现这样的问题,即多个进程所写的数据混在一起怎么办?幸好系统有这样的规则:一个write()调用可以写管道能容纳(Linux为4K字节)的任意个字节,系统将保证这些数据是分开的。这表示多个写操作的数据在FIFO文件中并不混合而将被维持分离的信息。