一、什么是命名管道(FIFO)?
- FIFO = First In First Out,先进先出
- 是一种文件类型(在文件系统里能看到)
- 用于无亲缘关系进程之间通信(普通管道只能父子进程)
- 半双工通信:数据只能单向流动
- 遵循 "读阻塞、写阻塞" 规则
一句话:命名管道 = 能跨进程通信的 "文件管道",任何进程打开它都能收发数据。
二、核心特点(必背)
- 以文件形式存在 (
p类型文件) - 无亲缘进程也能通信
- 阻塞默认行为
- 只打开读端 → 阻塞,直到有进程写
- 只打开写端 → 阻塞,直到有进程读
- 数据先进先出
- 数据一次性读取,读完就没了
三、创建 FIFO 的方法
命令行创建
bash
运行
mkfifo myfifo
查看类型:
bash
运行
ls -l
# 会看到 p--------- 1 root root ... myfifo
# p 就是管道文件
代码创建(C 语言)
c
运行
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
示例:
c
运行
mkfifo("/tmp/myfifo", 0666);
四、通信原理(超简单)
- 进程 A 以读方式打开 FIFO
- 进程 B 以写方式打开 FIFO
- B 写 → A 读
- 关闭文件 → 通信结束
五、最经典示例代码(可直接运行)
写进程(fifo_write.c)
c
运行
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
int main() {
// 1. 打开管道(写方式)
int fd = open("/tmp/myfifo", O_WRONLY);
char buf[100] = "Hello from FIFO writer!";
write(fd, buf, strlen(buf));
close(fd);
return 0;
}
读进程(fifo_read.c)
c
运行
#include <stdio.h>
#include <fcntl.h>
int main() {
// 1. 打开管道(读方式)
int fd = open("/tmp/myfifo", O_RDONLY);
char buf[100] = {0};
read(fd, buf, sizeof(buf));
printf("收到:%s\n", buf);
close(fd);
return 0;
}
六、运行方式
bash
运行
mkfifo /tmp/myfifo
# 终端1
./fifo_read
# 终端2
./fifo_write
你会看到读端立刻收到消息。
七、最常考面试题(我直接给答案)
1. 命名管道和匿名管道的区别?
- 匿名管道:只能父子 / 亲缘进程通信
- 命名管道:任意进程都能通信
- 匿名管道无文件,命名管道有文件
2. FIFO 默认是阻塞还是非阻塞?
阻塞。必须读写两端都打开,通信才开始。
3. 写端关闭后,读端会怎样?
read 返回 0,表示读到文件末尾。
4. 可以同时多个进程写吗?
可以,但不保证原子性,数据可能混乱。
八、一句话总结
命名管道就是一个管道文件,让任意两个进程能互相发数据,遵循先进先出、阻塞打开。