Linux系统篇23——进程(六):什么是进程间通信?一文搞懂背景与全貌

Linux系统篇23——进程(六):什么是进程间通信?一文搞懂背景与全貌 这一篇只把进程间通信这件事讲透它是什么、为什么需要、有哪些方式、各自怎么选。至于每种方式的具体原理、API 和代码实战会在后续文章中逐篇展开敬请关注。一、从一个问题说起进程为什么老死不相往来先做一个简单的实验。打开终端写下这样一段 C 代码// why_ipc.c —— 一个注定失败的全局变量通信尝试 #include stdio.h #include unistd.h int global_value 100; // 全局变量子进程能共享吗 int main(void) { pid_t pid fork(); if (pid 0) { /* 子进程修改全局变量 */ global_value 999; printf(Child sees global_value %d\n, global_value); return 0; } else { /* 父进程稍微等一下再看 */ sleep(1); printf(Parent sees global_value %d\n, global_value); } return 0; }编译运行你猜会输出什么gcc -Wall -o why_ipc why_ipc.c ./why_ipc结果是Child sees global_value 999 Parent sees global_value 100子进程明明把global_value改成了 999父进程读到的却还是 100。为什么因为fork()创建子进程时采用的是写时复制COWCopy-On-Write子进程先与父进程共享同一份物理内存一旦子进程试图修改数据内核就会为它复制一份独立的内存副本。从此父子进程各自持有自己的global_value修改互不影响。这就是操作系统进程隔离的核心每个进程都拥有独立的虚拟地址空间进程 A 的 0x1000 地址和进程 B 的 0x1000 地址根本不是同一块物理内存。这种隔离是安全的根基一个进程崩溃、被攻击、或者内存越界都影响不到其他进程。但代价是——进程之间无法直接交换数据了。于是操作系统提供了一系列桥让进程在保持隔离的同时还能协作这些桥统称为进程间通信IPC。二、什么是进程间通信IPC进程间通信IPCInter-Process Communication是指操作系统提供的、在多个进程之间传输数据和交换信息的一组机制。IPC 要解决的本质上是两类问题要解决的问题含义典型机制传输数据把一份数据从一个进程安全地送到另一个进程管道、消息队列、共享内存、Socket同步控制让多个进程在时间上协调配合避免互相踩踏信号量、信号两个进程要一起干活无外乎两种协作模式分工干活你算 A 部分我算 B 部分最后把结果汇总——需要传数据排队干活你干完我再干或者我负责生产你负责消费——需要同步。IPC 就是为这两种需求服务的。实际工程中通常数据传递 同步控制配合使用比如共享内存传大块数据 信号量保证读写顺序。三、为什么不能用全局变量来通信很多初学者会问既然进程需要共享数据为什么不用全局变量、或者把数据放到一个公共文件里读写回答分两层1. 全局变量在进程间是假共享。如开头实验所示进程各自有独立的地址空间全局变量在每个进程里都是独立副本修改互不可见。这恰恰是进程隔离要保证的。2. 共享一个文件也行但问题很多。两个进程同时读写同一个文件会出现并发写互相覆盖缺少原子性没有消息边界不知道读到哪算一条完整数据磁盘 IO 慢性能极差数据不落盘的话还要自己维护缓存。IPC 机制正是操作系统专门设计的带同步、带边界、高性能的进程协作方案比开个文件互相读写严谨得多。一句话进程之间天然共享不了变量只能通过操作系统提供的 IPC 通道来交流。四、IPC 方式全景图Linux 下的 IPC 机制经过几十年发展形成了两大体系 网络通信的格局各家机制可以归纳成一张总表类别代表机制一句话概括通信模型数据传输匿名管道 / 命名管道最古老的字节流管道单向、流式数据传输消息队列有类型的消息块双向、按类型共享存储共享内存最快的零拷贝共享直接读写同步控制信号量计数器式的同步原语互斥/同步事件通知信号异步通知只传编号单向、异步网络通信Socket能力最全面的通道双向、可跨主机五、六种 IPC 机制一句话定位先给大家一个整体印象每种机制的细节后面单篇展开① 管道Pipe像一根真实的管子一端写、一端读数据先进先出。匿名管道只能父子进程用命名管道FIFO任何进程都能用。适合简单的流式数据传输。② 消息队列Message Queue把数据打包成有类型、有边界的消息。接收方可以只取某一种类型的消息天然适合任务分发。数据经过内核性能中等。③ 共享内存Shared Memory把同一块物理内存映射到多个进程大家直接读写零拷贝、性能最高。但它不负责同步必须配信号量使用。④ 信号量Semaphore一个计数器专门用来同步控制多个进程互斥地访问共享资源或者实现我生产你消费的协作关系。它是共享内存的最佳搭档。⑤ 信号Signal一种异步事件通知进程收到信号后打断当前工作去执行处理函数。只能传一个整数编号传不了大块数据适合做提醒和唤醒。⑥ Socket原本为网络设计但本机进程也能用Unix Domain Socket还能跨主机通信TCP/UDP。能力最全面是高性能中间件Redis、Nginx 等本地通信的首选。记忆口诀小数据用管道有类型用队列大数据用共享内存跨机器用 Socket要同步找信号量只提醒发信号。六、如何快速选型选型其实就三步第一步先看是否跨主机。跨主机只有 SocketTCP/UDP可选其余全部出局。第二步再看数据量级。小数据、流式 → 管道 / 消息队列大块数据、高性能 → 共享内存务必配信号量需要高并发连接 → Unix Domain Socket。第三步最后看同步需求。凡是多个进程同时访问同一资源都别忘了同步——共享内存 信号量是经典组合Socket 则通常配合 IO 多路复用epoll。一张速查表送给你场景推荐方案父子进程传简单数据匿名管道无亲缘进程传流式数据命名管道 FIFO按类型分发任务消息队列大块数据、极致性能共享内存 信号量只做事件通知信号本机高并发服务通信Unix Domain Socket跨主机通信TCP / UDP Socket七、本篇总结最后用三句话收尾本篇进程天然隔离——每个进程有独立地址空间全局变量在进程间是假共享这是 IPC 存在的根本原因IPC 解决两类问题——传输数据管道、消息队列、共享内存、Socket和同步控制信号量、信号选型有规律——跨主机只能 Socket大数据量用共享内存同步必配信号量。