有名管道(fifo)
fifo 是在 pipe(无名管道) 的基础上,给 pipe 在文件系统中创建了一个 i-node(文件名)。但是 fifo 的文件内容仍然是保存在内核中。
①fifo 文件名随文件系统的持续性
②fifo 文件内容随内核持续性
fifo 和 pipe 是一样的,区别就是 fifo 在文件系统中有一个名字。
使用 fifo 需要操作 fifo 文件。也就是必须有一个管道文件
创建管道文件 fifo:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
参数:
@pathname: 要创建的 fifo 在Linux中的路径
@mode: 要创建的 fifo 文件的权限
1.宏形式: S_RUSR ...
2.八进制: 777
返回值: 成功返回 0
失败返回-1 并设置错误码 errno
注意事项: 不要在共享文件夹中创建 fifo ,windows 不支持管道文件
1.在 Linux 中手动创建
mkfifo my_fifo
2.使用代码创建 fifo
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
// argv[1] 表示待创建的fifo文件路径
int main(int argc,char *argv[])
{
int r = mkfifo(argv[1],0777);
if(r == -1)
{
perror("mkfifo error");
}
return 0;
}
fifo 的操作
1、打开管道文件
2、write/read数据
3、关闭管道文件
注意:
①fifo是有 i-node的,所以可以使用多个进程来读写文件!
②在收到 over 结束指令时,需要在break前输出一个换行,或者先关闭管道文件,在break。否则会因为缓冲区问题进入死循环。或者使用fflush(stdin);清空缓冲区。
代码实现:
write_fifo.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> // open 头文件
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> // close read write 头文件
#define N 30 // 一次最多读取的数据
int main(int argc,char *argv[])
{
// 1.打开一个有名管道
int fd = open(argv[1],O_RDONLY); // 只读打开
if(fd == -1)
{
perror("有名打开失败!");
exit(-1);
}
// 2.操作有名管道
char buf[N] = {0};
while(1)
{
int r = read(fd,buf,N);
if(r == -1)
{
perror("读取管道文件失败!");
break;
}
// 结束判断
if(strcmp(buf,"over") == 0)
{
printf("程序指令 over \n程序结束!\n");
printf("\n");
// close(fd);
// fd = 0;
break;
}
printf("读取管道数据:%s\n",buf);
}
// 3.关闭有名管道
if (fd) close(fd);
return 0;
}
read_fifo.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> // open 头文件
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> // close read write 头文件
#define N 30 // 保存一次最多能写入的数据
int main(int argc,char *argv[])
{
// 1.打开一个有名管道
int fd = open(argv[1],O_WRONLY); // 只写打开
if(fd == -1)
{
perror("管道开打开失败!");
exit(-1);
}
// 2.操作管道 往管道内写入数据 直到写入 over
char buf[N] = {0};
int w = 0;
while(1) // 循环写入数据
{
scanf("%s",buf);
w = write(fd,buf,strlen(buf));
if(w == -1)
{
perror("写入数据失败!\n");
break;
}
// 结束判断
if(strcmp(buf,"over") == 0)
{
printf("写入结束 over\n");
break;
}
}
// 3.关闭有名管道
close(fd);
return 0;
}