目录
[一、Linux IPC 的核心种类](#一、Linux IPC 的核心种类)
[2.IPC 对象通信(system v 标准)](#2.IPC 对象通信(system v 标准))
[3.socket 通信](#3.socket 通信)
[1. 核心特性](#1. 核心特性)
[4.示例代码:两个无亲缘进程通过 FIFO 通信](#4.示例代码:两个无亲缘进程通过 FIFO 通信)
一、Linux IPC 的核心种类
1.古老的通信方式
是 Linux 早期的基础 IPC 实现,包括:
- 无名管道
- 有名管道
- 信号
2.IPC 对象通信(system v 标准)
基于内核对象的通信方式,常用的有:
- 消息队列*(使用相对较少,这里不讨论)*
- 共享内存
- 信号量集
3.socket 通信
支持跨主机的网络级通信,核心场景是:
- 网络通信
注:管道的底层实现是队列**,数据遵循 "先进先出" 规则。
二、无名管道(匿名管道)
无名管道对应 pipe,是仅支持亲缘关系进程(如父子、兄弟进程)通信的方式。
1. 核心特性
- 仅能给亲缘关系进程通信;
- 半双工工作模式(实际编程按单工使用);
- 是特殊文件,不支持定位操作(lseek 对管道文件描述符 / 文件指针无效);
- 依赖文件 IO / 标准 IO 操作。
2.读写行为规则
管道的读写逻辑受缓冲区(默认 64K)和两端状态影响:
- 读端存在时,写端持续写超 64K 会阻塞(写得太快);
- 写端存在时,读端读空管道会阻塞(读得太快);
- 读端关闭后,写端写管道会导致写进程崩溃(管道破裂);
- 写端关闭后,读端读完管道内容,read 会返回 0,标志进程间通信结束。

3.编程顺序
创建管道 → fork子进程 → 读写管道 → 关闭管道
4.核心函数:pipe
cpp
int pipe(int pipefd[2]);
- 功能:创建并打开一个无名管道;
- 参数:pipefd[0] 是无名管道的固定读端,pipefd[1] 是固定写端;
- 返回值:成功返回 0,失败返回 - 1。
5.示例代码:父子进程通过无名管道通信
cpp
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
int main()
{
int pipe_fd[2];
pid_t pid;
char read_buf[1024] = {0};
const char *write_data = "Hello from parent (pipe)!";
// 1. 创建无名管道
if (pipe(pipe_fd) == -1)
{
perror("pipe create failed");
return -1;
}
// 2. fork创建子进程(建立亲缘关系)
pid = fork();
if (pid == -1)
{
perror("fork failed");
return -1;
}
// 3. 父进程:关闭读端,向管道写数据
if (pid > 0)
{
close(pipe_fd[0]); // 父进程仅写,关闭读端
write(pipe_fd[1], write_data, strlen(write_data));
close(pipe_fd[1]); // 写完关闭写端
wait(NULL); // 等待子进程执行完毕
}
// 4. 子进程:关闭写端,从管道读数据
else
{
close(pipe_fd[1]); // 子进程仅读,关闭写端
read(pipe_fd[0], read_buf, sizeof(read_buf));
printf("Child read: %s\n", read_buf);
close(pipe_fd[0]); // 读完关闭读端
}
return 0;
}
三、有名管道
有名管道对应 fifo,突破了亲缘关系限制,支持任意单机进程通信(只要知道管道的文件路径),且在文件系统中可见(有明确的路径名称)。
1.核心特性
- 可给任意单机进程通信,文件系统中可见(有路径);
- 基础特性与无名管道一致(半双工、特殊文件、不支持定位等);
- 额外特性:若管道一端未打开,open 函数会默认阻塞。
2.编程顺序
创建有名管道 → 打开有名管道 → 读写管道 → 关闭管道 → 卸载有名管道
3.核心函数:mkfifo
cpp
int mkfifo(const char *pathname, mode_t mode);
- 功能:在指定路径下创建一个有权限的有名管道文件;
- 参数:pathname 是有名管道的路径 + 名称,mode 是 8 进制的文件权限(如0666);
- 返回值:成功返回 0,失败返回 - 1。
4.示例代码:两个无亲缘进程通过 FIFO 通信
- 写进程(fifo_write.c):
cpp
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#define FIFO_PATH "/tmp/my_fifo"
int main()
{
// 1. 创建FIFO文件(已存在则忽略)
if (mkfifo(FIFO_PATH, 0666) == -1)
{
perror("mkfifo failed (ignore if exist)");
}
// 2. 打开FIFO文件(写模式)
int fd = open(FIFO_PATH, O_WRONLY);
if (fd == -1)
{
perror("open fifo failed");
return -1;
}
// 3. 向FIFO写数据
const char *msg = "Hello from FIFO write process!";
write(fd, msg, strlen(msg));
printf("Write to FIFO: %s\n", msg);
// 4. 关闭并卸载FIFO
close(fd);
unlink(FIFO_PATH);
return 0;
}
- 读进程(fifo_read.c):
cpp
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#define FIFO_PATH "/tmp/my_fifo"
int main()
{
char buf[1024] = {0};
// 1. 打开FIFO文件(读模式,阻塞等待写端)
int fd = open(FIFO_PATH, O_RDONLY);
if (fd == -1) {
perror("open fifo failed");
return -1;
}
// 2. 从FIFO读数据
read(fd, buf, sizeof(buf));
printf("Read from FIFO: %s\n", buf);
// 3. 关闭FIFO
close(fd);
return 0;
}
四、无名管道与有名管道核心对比
| 对比维度 | 无名管道(pipe) | 有名管道(FIFO) |
|---|---|---|
| 通信范围 | 仅亲缘关系进程 | 任意单机进程 |
| 文件系统可见性 | 不可见(内核维护) | 可见(有路径的特殊文件) |
| 打开特性 | fork 后继承文件描述符 | 一端未打开时 open 默认阻塞 |
| 生命周期 | 随进程退出自动释放 | 需手动 unlink 删除 |
| 创建方式 | pipe () 函数 | mkfifo () 函数 |
五、总结
- 管道是 Linux 最基础的 IPC 机制,核心分为无名管道(pipe)和有名管道(FIFO)两类,均为半双工、基于队列的特殊文件;
- 无名管道仅支持亲缘进程通信,无需手动清理;有名管道支持任意单机进程通信,需手动创建 / 删除;
- 管道读写需遵循核心规则,尤其注意 "读 / 写端关闭" 后的行为,避免进程崩溃或数据异常。