示例代码
- github: https://github.com/lengjingzju/notes/tree/master/code/linux_ipc
- gitee: https://gitee.com/lengjingzju/notes/tree/master/code/linux_ipc
一、Linux IPC 概述
在 Linux 系统中,进程间通信(IPC,Inter-Process Communication) 是指在不同进程之间传递数据或信号的机制。由于每个进程拥有独立的虚拟地址空间,一个进程无法直接访问另一个进程的数据,因此需要借助操作系统提供的 IPC 工具来实现进程间的协作与同步。
IPC 不仅是操作系统课程的核心内容,更是实际开发中构建高性能、可扩展系统的基础技能。无论是构建多进程服务器、实现进程间任务协同,还是进行资源同步与数据共享,掌握 IPC 都是 Linux 后端开发工程师的必备能力。
二、IPC 工具分类
根据功能和用途,Linux IPC 工具可分为以下几类:
1. 通信工具
用于在进程之间传递数据。
数据传输
- 字节流:数据以无边界字节流形式传输
- PIPE(无名管道)
- FIFO(命名管道)
- TCP 套接字
- 消息:数据以有边界消息形式传输
- SYSV 消息队列
- POSIX 消息队列
- UDP 套接字
- 伪终端:模拟终端设备,用于进程间通信
共享内存
将一块内存区域映射到多个进程的地址空间,进程可直接读写该区域。
- SYSV 共享内存
- POSIX 共享内存
- 文件内存映射
- 匿名内存映射
2. 同步工具
用于协调进程或线程的执行顺序,防止竞争条件。
线程同步(同一进程内)
- mutex(互斥量)
- rwlock(读写锁)
- cond(条件变量)
- spin(自旋锁)
- barrier(屏障)
进程同步
- 文件锁
- 记录锁(fcntl)
- 文件锁(flock)
- 信号量
- SYSV 信号量
- POSIX 命名信号量
- POSIX 无名信号量
- 信号:常称为软中断,有中断号,用于通知进程事件发生
三、IPC 工具属性对比
下表总结了常用 IPC 工具的关键特性:
| PIPE无名管道 | 无名 | 文件描述符 | 相关进程 | 进程 |
| FIFO命名管道 | 文件路径名 | 文件描述符 | 权限掩码 | 进程 |
| SYSV消息队列 | IPC键key_t | IPC标识符int | 权限掩码 | 内核 |
| SYSV信号量 | IPC键key_t | IPC标识符int | 权限掩码 | 内核 |
| SYSV共享内存 | IPC键key_t | IPC标识符int | 权限掩码 | 内核 |
| POSIX消息队列 | IPC路径名 | mqd_t描述符 | 权限掩码 | 内核 |
| POSIX命名信号量 | IPC路径名 | sem_t*指针 | 权限掩码 | 内核 |
| POSIX共享内存 | IPC路径名 | 文件描述符 | 权限掩码 | 内核 |
| 文件内存映射 | 路径名 | 文件描述符 | 权限掩码 | 文件 |
| 匿名内存映射 | 无名 | 无 | 相关进程 | 进程 |
| flock()文件锁 | 文件路径名 | 文件描述符 | open()操作 | 进程 |
| fcntl()文件锁 | 文件路径名 | 文件描述符 | open()操作 | 进程 |
| TCP套接字 | IP+端口 | 文件描述符 | 任意进程 | 进程 |
| UDP套接字 | IP+端口 | 文件描述符 | 任意进程 | 进程 |
| Unix域套接字 | 路径名 | 文件描述符 | 权限掩码 | 进程 |
| POSIX无名信号量 | 无名 | sem_t*指针 | 内存权限 | 进程 |
| POSIX互斥锁 | 无名 | pthread_mutex_t* | 同一进程 | 进程 |
| POSIX读写锁 | 无名 | pthread_rwlock_t* | 同一进程 | 进程 |
| POSIX条件变量 | 无名 | pthread_cond_t* | 同一进程 | 进程 |
关键术语解释
- 相关进程:同一进程通过 fork() 创建的进程(父子进程或兄弟进程)
- 权限掩码:通过文件系统权限控制访问
- 持久性:
- 进程持久性:IPC 对象持续到最后一个使用它的进程关闭或关闭该对象为止
- 注:FIFO特殊,所有进程关闭了FIFO,但文件系统的FIFO节点一直保持着,需要unlink()显式删除
- 内核持久性:IPC 对象持续到内核重启或显式删除为止
- 文件系统持久性:IPC 对象持续到显式删除,内核重启不影响
- 进程持久性:IPC 对象持续到最后一个使用它的进程关闭或关闭该对象为止
- POSIX的IPC路径名以 / 开头,且后面的路径不含 /
四、数据传输与共享内存机制
数据传输机制
- 读取操作是破坏性的,数据被消耗后其他进程无法再次读取
- 默认情况下,空读/满写会阻塞进程
- 字节流无边界,可读取任意字节
- 消息有边界,一次读取一条完整消息
共享内存机制
- 文件映射:基于文件内容初始化内存
- 匿名映射:分配新内存区域
五、IPC 选择策略
选择依据
通信模式
- 一对一 vs 一对多 vs 多对多
- 单向 vs 双向
性能要求
- 共享内存 > 消息队列 > 管道 > 套接字(本地通信)
平台兼容性
- POSIX IPC 标准化程度高,可移植性好
- System V IPC 历史悠久,广泛支持
开发复杂度
- 管道和 FIFO 简单易用
- 共享内存需要额外同步机制
持久性需求
- 是否需要跨进程生命周期的持久存储
典型应用场景
- 父子进程通信:PIPE
- 任意进程通信:FIFO、消息队列、共享内存
- 高性能数据共享:共享内存 + 信号量
- 网络通信:套接字
- 线程同步:互斥锁、条件变量
- 进程同步:信号量、文件锁
六、示例代码概览
在本次系列文章中,我们将以统一的示例模式演示各种 IPC 机制:父进程(或主线程)从终端读取数据,通过 IPC 机制传递给子进程(或子线程),子进程将数据输出到终端。输入 “q” 退出程序。
示例程序包括:
- test_pipe.c – PIPE(无名管道)示例
- test_fifo.c – FIFO(命名管道)示例
- test_sysv_msg.c – SYSV 消息队列示例
- test_sysv_shm.c – SYSV 共享内存示例
- test_posix_mq.c – POSIX 消息队列示例
- test_posix_shm.c – POSIX 共享内存示例
- test_thread_cond.c – 线程条件变量示例
- test_thread_sem.c – 线程信号量示例
- test_signal_sender.c / test_signal_reciver.c – 信号通信示例
七、系列文章安排
本系列将分六篇文章深入讲解 Linux IPC:
八、总结
Linux IPC 提供了丰富多样的进程间通信与同步机制,每种机制都有其适用场景和优缺点。选择合适的 IPC 机制需要综合考虑通信模式、性能需求、平台兼容性和开发复杂度等因素。
掌握 IPC 不仅是理解操作系统原理的关键,更是构建高性能、可靠分布式系统的基础。通过本系列文章,我们将从理论到实践,全面掌握 Linux IPC 的方方面面,为开发高效的多进程/多线程应用打下坚实基础。
在接下来的文章中,我们将从最简单的 PIPE 和 FIFO 开始,逐步深入各种 IPC 机制的内部原理和实际应用,敬请期待!
下一篇预告:我们将深入讲解 PIPE(无名管道)和 FIFO(命名管道),这是 Linux 中最基本、最常用的进程间通信方式,通过实际代码示例展示其工作原理和使用方法。



