fifo
命名管道
FIFO常被称为命名管道, 以区分管道(pipe). 管道(pipe)只能用于"有血缘关系"的进程间. 但通过FIFO, 不相关的进程也能交换数据
FIFO是linux基础文件类型中的一种. 但FIFO文件在磁盘上没有数据块, 仅仅用来标识内核中一条通道. 各个进程可以打开这个文件进程read/write, 实际上是在读写内核通道, 这样就实现了进程间的通信
特点
有名管道
在磁盘上有这样一个文件
伪文件, 在磁盘上大学为0
在内核中有一个对应的缓冲区
半双工的通信方式
使用场景
没有血缘关系的进程间通信
创建方式
命令: mkfifo管道名
函数: int mkfifo(const char *pathname, mode_t mode);
fifo文件可以使用IO函数进行操作
open/close
read/write
不能执行lseek操作
进程间通信
两个不相干的进程, 进程A(a.c)和进程B(b.c)
a.c:
int fd = open("mufifo", O_RDONLY);
read(fd, buf, sizeof(buf));
close(fd);
b.c
int fd = open("myfifo", O_WRONLY);
write(fd, "Hello World", 11);
close(fd)
注意: a.c和b.c中open的文件需要打开一个fifo
实例程序
测试时要先关闭读端再关闭写端, 否则写端关闭后读端一直读0
写端
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, const char *argv[]) {
if (argc < 2) {
printf("./a.out, fifoname\n");
exit(1);
}
int ret = access(argv[1], F_OK); // 判断文件是否存在
if (ret == -1) {
int r = mkfifo(argv[1], 0664); // 创建fifo
if (r == -1) {
perror("mkfifo error");
exit(1);
}
printf("有名管道%s创建成功\n", argv[1]);
}
int fd = open(argv[1], O_WRONLY);
if (fd == -1) {
perror("open error");
exit(1);
}
char *p = "haha";
while (1) {
//int len = write(fd, p, sizeof(p)); // 好像和编码方式有关
int len = write(fd, p, strlen(p)+1);
printf("write: %s\nlen = %d\n", p, len);
sleep(1);
}
close(fd);
return 0;
}
读端
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, const char *argv[]) {
if (argc < 2) {
printf("./a.out, fifoname\n");
exit(1);
}
int ret = access(argv[1], F_OK); // 判断文件是否存在
if (ret == -1) {
int r = mkfifo(argv[1], 0664); // 创建fifo
if (r == -1) {
perror("mkfifo error");
exit(1);
}
printf("有名管道%s创建成功\n", argv[1]);
}
int fd = open(argv[1], O_RDONLY);
if (fd == -1) {
perror("open error");
exit(1);
}
char buf[512];
while (1) {
int len = read(fd, buf, sizeof(buf));
buf[len] = 0;
printf("read: %s\nlen = %d\n", buf, len);
}
close(fd);
return 0;
}