Linux 命名管道(FIFO)通信
在 Linux 进程间通信(IPC)中,管道是最基础、最常用的通信方式之一。平时接触的'匿名管道'有一个致命缺陷——只能用于有血缘关系的进程(父进程与子进程、兄弟进程),无法实现无关联进程间的通信。
Linux 命名管道(FIFO)通过文件系统标识实现无血缘关系进程间的字节流通信。它解决了匿名管道仅限父子进程的问题,支持跨进程交互。核心特点包括半双工、阻塞特性及基于文件路径访问。创建方式支持命令行 mkfifo 和代码 mkfifo 函数。实际开发中需注意打开规则(读写端同步)、权限设置、SIGPIPE 信号处理及文件残留清理。适用于后台服务控制、独立程序数据交互等场景。

在 Linux 进程间通信(IPC)中,管道是最基础、最常用的通信方式之一。平时接触的'匿名管道'有一个致命缺陷——只能用于有血缘关系的进程(父进程与子进程、兄弟进程),无法实现无关联进程间的通信。
命名管道(简称 FIFO),正是为解决这个问题而生。它给管道赋予了一个'文件名',通过文件系统作为媒介,让任意两个进程(无论是否有血缘关系)都能通过这个'命名'实现数据交互。
命名管道和匿名管道的核心通信逻辑完全一致——都是基于'字节流'的半双工通信(同一时刻只能单向传输数据),底层都是内核中的缓冲区。
两者的核心区别是:命名管道有一个可见的文件系统入口(一个以.fifo 或.pipe 为后缀的文件),这个文件只是一个'标识',不存储实际数据(数据仍在内存缓冲区中);而匿名管道没有文件入口,只能通过父子进程继承文件描述符来通信。
简单来说:匿名管道是'隐式的、血缘专属',命名管道是'显式的、通用的',只要知道 FIFO 文件的路径,任意进程都能与之通信。


为了更清晰区分,做一个简单对比表,避免混淆:
| 对比维度 | 匿名管道(pipe) | 命名管道(FIFO) |
|---|---|---|
| 通信范围 | 有血缘关系的进程(父子、兄弟) | 任意进程(无血缘关系也可) |
| 标识方式 | 无文件标识,通过文件描述符继承 | 有文件系统入口(FIFO 文件) |
| 创建方式 | 通过 pipe() 系统调用创建 | 通过 mkfifo() 系统调用或 mkfifo 命令创建 |
| 生命周期 | 随进程退出而销毁(文件描述符关闭) | 随 FIFO 文件删除而销毁,进程退出不影响文件 |
| 使用场景 | 父子进程间简单通信(如 shell 管道) | 无关联进程间通信(如两个独立程序交互) |
命名管道有两种创建方式:命令行创建和代码创建,本质都是在文件系统中生成一个 FIFO 类型的文件。
直接通过 mkfifo 命令创建命名管道,语法简单,适合快速测试:
# 创建名为 myfifo 的命名管道
mkfifo myfifo
# 查看管道文件(类型标识为 p)
ls -l myfifo
我们可以发现,这里创建的管道文件 (最前面的标识是 p 开头),就算我们是不停地往里面进行写操作,但是它的文件大小是一直不变的,验证了我们上面图中所说的它不是一个普通文件。
通过 mkfifo() 系统调用在代码中创建命名管道,需指定管道路径和权限,原型如下:
#include <sys/stat.h>
#include <sys/types.h>
// 参数:pathname-管道路径;mode-权限(如 0644)
int mkfifo(const char *pathname, mode_t mode);
代码示例(创建命名管道)
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#define FIFO_PATH "./myfifo"
int main() {
// 创建命名管道,权限 0644(所有者读 + 写,其他读)
int ret = mkfifo(FIFO_PATH, 0644);
if (ret == -1) {
// 若管道已存在,errno 为 EEXIST,可忽略该错误
if (errno != EEXIST) {
perror("mkfifo error");
return 1;
}
printf("命名管道已存在\n");
} else {
printf("命名管道创建成功\n");
}
return 0;
}
命名管道的打开(open())行为与普通文件不同,核心是'读端与写端的同步'——仅当管道的读端和写端都被打开后,通信才能正常进行,具体规则如下:
注意:实际开发中,建议读端以O_RDONLY打开,写端以O_WRONLY打开,避免使用 O_RDWR(可能导致通信逻辑混乱)。
Makefile:
all: client server
client: client.cpp
g++ -o $@ $^ -std=c++11
server: server.cpp
g++ -o $@ $^ -std=c++11
.PHONY: clean
clean:
rm -f client server
comm.h:
#pragma once
#include <string>
const std::string fifoname="fifo";
#include <iostream>
#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "comm.h"
int main() {
// 1. 创建管道文件
umask(0);
int n = mkfifo(fifoname.c_str(), 0666);
if (n < 0) {
perror("mkfifo");
return 1;
}
// 2. 打开管道文件
int rfd = open(fifoname.c_str(), O_RDONLY);
if (rfd < 0) {
perror("open");
return 2;
}
char inbuffer[1024];
// 3. 进行通信
while (true) {
ssize_t n = read(rfd, inbuffer, sizeof(inbuffer) - 1);
if (n > 0) {
inbuffer[n] = 0;
std::cout << "client say# " << inbuffer << std::endl;
} else if (n == 0) {
// 写端关闭了
break;
} else {
perror("read");
break;
}
}
// 4. 关闭
close(rfd);
// 5. 删除管道文件
unlink(fifoname.c_str());
return 0;
}
#include <iostream>
#include <string>
#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "comm.h"
int main() {
int wfd = open(fifoname.c_str(), O_WRONLY);
if (wfd < 0) {
perror("open");
return 1;
}
std::string outstring;
while (true) {
std::cout << "Please Enter@ ";
std::cin >> outstring;
write(wfd, outstring.c_str(), outstring.size()); // 要不要写'\0'? 不需要!
}
close(wfd);
return 0;
}

命名管道因其'跨进程、简单易用'的特点,在 Linux 开发中应用广泛,常见场景包括:
命名管道(FIFO)是 Linux 跨进程通信的基础方式,核心是'通过文件系统标识,实现任意进程间的字节流通信'。它继承了匿名管道的简单性,又解决了匿名管道'只能用于血缘进程'的缺陷,是入门 IPC 开发的必学知识点。
重点掌握 FIFO 的阻塞特性、SIGPIPE 信号处理和文件删除问题,就能避免绝大多数踩坑场景。
实际开发中,若需要更高效、更复杂的通信(如消息优先级、双向通信的更优实现),可后续学习消息队列、共享内存等 IPC 机制,但命名管道的核心思想(字节流、文件标识),是理解所有 IPC 机制的基础。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online