1、FIFO文件介绍
FIFO文件(也称为命名管道)是一种特殊类型的文件,在linux中用于进程间通信。而FIFO文件允许不相关进程通过读取和写入相同的文件夹来进行通信。
特点:
- FIFO文件位于文件系统中,可以像其他文件一样进行访问和管理。
- FIFO文件可以通过名称进行识别和引用,而不仅仅依赖于文件描述符(无名管道只依赖于文件描述符)。
- FIFO文件可以在不同的进程之间进行双向通信,允许同时进行读取和写入操作(但是容易出现数据混乱,也就是数据会交织在一起)。
2、FIFO实现原理
底层通过mkfifo函数创建一个FIFO文件,FIFO文件对应一个fifo inode,fifo iNode和pipe inode底层实现相同。
命名管道通过文件名创建管道,所以称为命名管道。
命名管道通过mkfifo创建完成之后,进程调用open打开fifo文件,由于每个文件都对应唯一的iNode节点,所以多个进程都是打开相同的iNode节点,成功打开fifo文件之后,进程能正常读写管道完成进程间通信。
打开fifo文件需要知道fifo文件路径,进程间只要知道fifo文件路径,就能建立连接,完成通信。进程之间都能看到管道内存空间,所以进程能正常通信。
3、FIFO是否支持全双工
- 调用一次mkfifo函数只能产生一个管道(一个缓冲区),所以命名管道是半双工模式。
- 多个进程同时读写一个命名管道可能会出现数据异常,所以进程调用open函数时指定打开标志为O_RDONLY或者O_WRONLY
- 若要实现全双工通信,需要创建多个命名管道。
4、FIFO编程
创建命名管道:
int mkfifo(const char *pathname, mode_t mode);
功能:
mkfifo函数是Linux下的一个系统调用函数,用于一个命名管道(FIFO文件)的创建。
参数:
path:命名管道路径名
mode:创建的命名管道的权限,可参考open函数
返回值:
成功:返回0
失败:返回-1,并设置errno
命名管道使用文件IO open、write、read、close实现打开、写、读、关闭操作。
5、写个例程
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define FIFO_PATH "/home/fqs/UNIX_C/001_FIFO/test"
int fifo_read()
{
int ret = mkfifo(FIFO_PATH, 0644);
if(ret == -1 && errno != EEXIST)
{
perror("mkfifo");
return -1;
}
int fd = open(FIFO_PATH, O_RDONLY);
if(fd == -1)
{
perror("open");
return -1;
}
while(1)
{
char buf[1024] = {0};
read(fd, buf, 1024);
printf("read buf = %s\n",buf);
sleep(1);
}
return 0;
}
int fifo_write(const char *buf)
{
int ret = mkfifo(FIFO_PATH, 0644);
if(ret == -1 && errno != EEXIST)
{
perror("mkfifo");
return -1;
}
int fd = open(FIFO_PATH, O_WRONLY);
if(fd == -1)
{
perror("open");
return -1;
}
while(1)
{
write(fd, buf, strlen(buf));
printf("write buf = %s\n",buf);
sleep(1);
}
return 0;
}
int main(int argc, char *argv[])
{
int mode = atoi(argv[1]);
char *buf = argv[2];
if(mode == 0)
{
fifo_read();
}
else if(mode == 1)
{
fifo_write(buf);
}
return 0;
}
传参为0,从管道中读数据,传参为1,向管道写入argv[2]。