命名管道(FIFO)和管道(pipe)基本相同,但也有一些不同的地方:
1)FIFO在文件系统中作为一个特殊的文件而存在,但FIFO中的内容却存放在内存中。(某个目录下有一个文件名)
2)当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用。
3)FIFO有名字,不相关的进程可以通过打开命名管道进行通信。
FIFO文件的创建
#include
#include
int mkfifo(const char * pathname, mode_t mode);
参数:pathname是FIFO的路径名+文件名;mode是mode_t类型的权限描述符。
返回值:成功返回0;失败返回-1(如果文件已经存在会失败).
注意:不能用touch命令或者新建文件的方式来创建命名管道。
命名管道必须用特殊的函数mkfifo来创建。
操作FIFO文件时的特点:系统调用的I/O函数都可以作用于FIFO,如open、close、read、write等。
1)未指定O_NONBLOCK(即是阻塞的方式)时,默认是阻塞的
---- 当open以只读方式打开FIFO时,要阻塞到某个进程为写而打开此FIFO。
---- 当open以只写方式打开FIFO时,要阻塞到某个进程为读而打开此FIFO。
#include
#include
#include
#include
#include
#include
int main(int argc,char * argv[])
{
int fd;
int ret;
ret = mkfifo("my_fifo",S_IRUSR|S_IWUSR);
if(ret != 0){
perror("mkfifo");
}
printf("before open.\n");
fd = open("my_fifo",O_RDONLY);
if(fd < 0){
perror("open file.");
}
printf("after open.\n");
}
输出如下:
默认情况下,open是带阻塞的,必须有另外一个进程以只写的方式打开也行,所以只输出一行。
即不指定O_NONBLOCK时,open,read,write都是带阻塞的。
#include
#include
#include
#include
#include
#include
int main(int argc,char * argv[])
{
int fd;
int ret;
ret = mkfifo("my_fifo",S_IRUSR|S_IWUSR);
if(ret != 0){
perror("mkfifo");
}
printf("before open.\n");
fd = open("my_fifo",O_RDONLY|O_NONBLOCK);
if(fd < 0){
perror("open file.");
}
printf("after open.\n");
}
输出:
---- 当open以只读、只写方式打开FIFO时会阻塞,调用read函数从FIFO里读数据时read也会阻塞。
---- 通信过程中若写进程先退出了,则调用read函数从FIFO中读数据时不阻塞;若写进程又重新运行,则调用read函数从FIFO里读数据时又恢复阻塞。
---- 通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到SIGPIPE信号)退出。
---- 调用write函数向FIFO里写数据,当缓冲区已满时,write也会阻塞。
2)打开FIFO时,设置非阻塞标志O_NONBLOCK
---- 先以只读方式打开:如果没有进程已经为写而打开一个FIFO,只读open成功,并且open不阻塞。
---- 先以只写方式打开:如果没有进程已经为读而打开一个FIFO,只写open将出错返回-1.
---- read、write读写命名管道中读数据时不阻塞。
(读时管道中有数据直接读,无数据出错;写时管道没有满可以直接写,如果管道满了,写出错)
---- 通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到SIGPIPE信号)退出。
fifo_read_5.c如下:
#include
#include
#include
#include
#include
#include
int main(int argc,char * argv[])
{
int fd;
int ret;
ret = mkfifo("my_fifo",S_IRUSR|S_IWUSR);
if(ret != 0){
perror("mkfifo");
}
printf("before open.\n");
fd = open("my_fifo",O_RDONLY|O_NONBLOCK);
if(fd < 0){
perror("open file.");
}
while(1){
char recv[100];
bzero(recv,sizeof(recv));
read(fd,recv,sizeof(recv));
printf("read from my_fifo buf = [%s]\n",recv);
sleep(1);
}
return 0;
}
fifo_write_5.c如下
#include
#include
#include
#include
#include
#include
int main(int argc,char * argv[])
{
int fd;
char wr[100] = "hello my name is carie.";
fd = open("my_fifo",O_WRONLY|O_NONBLOCK);
if(fd < 0){
perror("open fifo.");
return 0;
}
while(1){
write(fd,wr,strlen(wr));
printf("write to my_fifo buf = %s\n",wr);
sleep(1);
}
return 0;
}
编译执行结果:先运行read,后运行write,当read这边用ctrl+c结束后,write端也会自动结束。
Semantically, a FIFO is similar to a pipe. The principal difference is that a FIFO has a name within the file system and is opened in the same way as a regular file. This allows a FIFO to be used for communication between unrelated processes.(e.g a client and server) Just as with pipes, a FIFO has a write end and a read end, and data is read from the pipe in the same order as it is written. This fact gives FIFOs their name: first in, first out. FIFOs are also sometimes known as named pipes.
we can create a FIFO from the shell using the mkfifo command:
$ mkfifo [-m mode] pathname
The pathname is the name of the FIFO to be created, and the -m option is used to specify a permission mode in the same way as for the chmod command.
Generally, the only sensible(合乎情理的) use of a FIFO is to have a ready process and a writing process on each end. Therefore, by default, opening a FIFO for reading (the open() O_RDONLY flag) blocks until another process opens the FIFO for writing (the open() O_WRONLY flag). Conversely(相反地), opening the FIFO for writing blocks until another process opens the FIFO for reading.