
Linux 系统中,每个进程有独立的地址空间,一个进程不能直接访问另一个进程的内存。但很多时候进程之间需要交换数据、协调工作。Linux 提供了多种进程间通信(IPC)机制,各有适用场景。
今天介绍 5 种常用的 IPC 方式,理解它们的特点和适用场景。
1. 管道(Pipe)
管道是最古老的 IPC 机制,Unix 早期就有了。它是单向的字节流,把一个进程的标准输出连接到另一个进程的标准输入。
# 命令行里的管道就是典型应用cat file.txt | grep "keyword" | wc -l
管道分为匿名管道和命名管道(FIFO)。匿名管道只能用于父子进程之间,命名管道则有文件名,可以在无关进程间使用。
管道的特点是简单、单向、基于字节流。适合生产者-消费者模式,但不适合需要双向通信或复杂数据结构的场景。
2. 消息队列(Message Queue)
消息队列克服了管道的一些限制。它允许一个或多个进程写入消息,一个或多个进程读取消息。
与管道不同,消息队列:
消息队列适合需要按类型处理消息的场景,比如任务调度系统把不同类型的任务发到不同队列。
3. 信号(Signal)
信号是 Unix 系统最古老的 IPC 机制之一,用于通知进程发生了某个事件。
常见信号:
信号是异步的,进程不知道什么时候会收到信号。信号处理函数要尽量简单快速,因为信号会打断进程的正常执行流程。
信号适合传递简单通知,不适合传输数据。比如父进程通知子进程"该退出了",或者监控进程发现异常时重启服务。
4. 信号量(Semaphore)
信号量不是用来传数据的,而是用来同步进程、协调对共享资源的访问。
信号量本质上是一个计数器。进程可以对信号量做两种操作:
- • P 操作(wait):信号量值减 1,如果值为负则阻塞
- • V 操作(signal):信号量值加 1,唤醒等待的进程
经典场景是控制同时访问某资源的进程数。比如一个数据库连接池有 10 个连接,用初始值为 10 的信号量控制,每个进程获取连接前执行 P 操作,释放连接后执行 V 操作。
5. 共享内存(Shared Memory)
共享内存是最快的 IPC 方式。多个进程把同一块物理内存映射到自己的虚拟地址空间,直接读写这块内存就能交换数据,不需要内核介入。
共享内存的问题是:进程需要自己做同步。如果两个进程同时写同一块内存,数据就会乱套。所以共享内存通常配合信号量或互斥锁使用。
适合场景:大数据量、高频率的进程间通信。比如视频编解码器,一帧图像几 MB,用管道或消息队列复制数据太慢,共享内存是更好的选择。
对比总结
实际应用中的选择
现代 Linux 系统还提供了更高级的 IPC 机制,比如 Unix Domain Socket、D-Bus 等。但理解这 5 种基础机制,对理解操作系统原理和排查问题都很有帮助。