729 字
2 分钟
OS笔记(四):进程通信
OS笔记(四):进程通信
本文是操作系统笔记系列的第四篇,详细讲解进程间通信(IPC)的三种基本方式,以及Linux中IPC的实际使用方法。
📚 目录
一、为什么需要进程通信?
1.1 进程的独立性
进程是分配系统资源的基本单位,各进程的内存地址空间相互独立:

### 1.2 安全考虑
为了保证安全,**一个进程不能直接访问另一个进程的地址空间**。因此需要操作系统提供专门的通信机制。
### 1.3 IPC的三种方式
| 方式 | 原理 | 特点 ||------|------|------|| **共享存储** | 在内存中开辟共享区域 | 速度快,需要同步 || **消息传递** | 通过发送/接收消息 | 灵活,开销较大 || **管道通信** | 通过管道文件连接 | 简单,单向传输 |
---
<a id="共享存储"></a>## 二、共享存储
### 2.1 基本原理
操作系统在内存中划出一块**共享存储区**,多个进程可以访问这块区域进行数据交换。

### 2.2 两种类型
| 类型 | 说明 | 特点 ||------|------|------|| **基于数据结构的共享** | 共享固定大小的数据结构(如数组) | 限制多、速度慢、**低级通信** || **基于存储区的共享** | 共享原始内存区域,数据形式由进程自定 | 灵活、速度快、**高级通信** |
### 2.3 同步互斥
多个进程访问共享空间时需要**互斥**,通常使用操作系统提供的同步互斥工具(如P、V操作、信号量)。
---
<a id="消息传递"></a>## 三、消息传递
### 3.1 基本原理
进程间的数据交换以**格式化的消息**为单位,通过操作系统提供的"发送消息/接收消息"原语进行数据交换。
消息结构:3.2 两种方式
直接通信方式
发送方和接收方直接指定对方,点名道姓的消息传递。

间接通信方式
通过**信箱(Mailbox)**作为中间实体进行消息传递。

| 对比 | 直接通信 | 间接通信 |
|---|---|---|
| 寻址 | 直接指定进程PID | 通过信箱名 |
| 耦合度 | 高 | 低 |
| 灵活性 | 低 | 高 |
四、管道通信
4.1 基本原理
管道(Pipe)是连接两个进程的共享文件,一个进程写入数据,另一个进程读取数据。

4.2 管道的特点
| 特点 | 说明 |
|---|---|
| 半双工 | 某一时间段内只能单向传输 |
| 互斥访问 | 各进程要互斥地访问管道 |
| 写满阻塞 | 管道写满时,写进程阻塞 |
| 读空阻塞 | 管道读空时,读进程阻塞 |
| 数据消失 | 数据一旦被读出就消失 |
4.3 读写规则
> **Linux方案**:一个管道允许**多个写进程**和**一个读进程**,或者**多个写进程**和**多个读进程**。
---
<a id="信号"></a>## 五、信号
### 5.1 信号的概念
信号(Signal)是用于通知进程某个**特定事件已经发生**的机制。进程收到信号后进行相应处理。
### 5.2 信号的发送与保存

### 5.3 信号的处理时机
当进程从**内核态**转为**用户态**时,检查是否有待处理信号。

### 5.4 信号的处理方式
| 处理方式 | 说明 ||----------|------|| **默认处理** | 执行OS设置的缺省信号处理程序 || **自定义处理** | 用户注册的信号处理函数(覆盖默认) || **忽略** | 某些信号可以被忽略 |
### 5.5 信号处理规则
1. 处理完信号后,返回进程的下一条指令继续执行2. 一旦处理了某个信号,pending位重置为03. 重复收到的同类信号被丢弃4. 同时收到多个信号时,先处理序号更小的5. 某些信号不能被自定义处理或阻塞(如SIGKILL、SIGSTOP)
---
<a id="linux"></a>## 六、Linux实战:进程通信
### 6.1 管道通信
```bash# 匿名管道(父子进程间)ls | grep ".txt"
# 创建命名管道(任意进程间)mkfifo /tmp/my_pipe
# 写入端echo "Hello from writer" > /tmp/my_pipe &
# 读取端cat /tmp/my_pipe6.2 共享内存
# 使用ipcs查看共享内存ipcs -m
# Python共享内存示例python3 << 'EOF'import multiprocessingimport time
def writer(shm): shm.buf[:5] = b'Hello' print("写入完成")
def reader(shm): time.sleep(1) print(f"读取: {bytes(shm.buf[:5])}")
if __name__ == '__main__': shm = multiprocessing.shared_memory.SharedMemory(create=True, size=1024)
p1 = multiprocessing.Process(target=writer, args=(shm,)) p2 = multiprocessing.Process(target=reader, args=(shm,))
p1.start() p2.start() p1.join() p2.join()
shm.close() shm.unlink()EOF6.3 消息队列
# 查看消息队列ipcs -q
# Python消息队列示例python3 << 'EOF'from multiprocessing import Queue, Process
def sender(q): q.put("Hello from sender") q.put(42)
def receiver(q): print(f"收到: {q.get()}") print(f"收到: {q.get()}")
if __name__ == '__main__': q = Queue() p1 = Process(target=sender, args=(q,)) p2 = Process(target=receiver, args=(q,)) p1.start() p1.join() p2.start() p2.join()EOF6.4 信号
# 查看所有信号kill -l
# 发送信号kill -SIGUSR1 <PID> # 发送用户自定义信号kill -SIGTERM <PID> # 请求终止kill -SIGKILL <PID> # 强制终止
# Python信号处理python3 << 'EOF'import signalimport os
def handler(signum, frame): print(f"收到信号 {signum}")
signal.signal(signal.SIGUSR1, handler)
print(f"PID: {os.getpid()}")print("等待信号 SIGUSR1...")signal.pause()EOF6.5 Socket通信
# 服务器端python3 -c "import sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind(('localhost', 12345))s.listen(1)conn, addr = s.accept()data = conn.recv(1024)print(f'收到: {data.decode()}')conn.send(b'Hello from server')conn.close()" &
# 客户端python3 -c "import sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(('localhost', 12345))s.send(b'Hello from client')data = s.recv(1024)print(f'收到: {data.decode()}')s.close()"七、本章小结
核心概念
| 概念 | 要点 |
|---|---|
| 共享存储 | 开辟共享内存区,需要同步互斥 |
| 消息传递 | 发送/接收消息,直接或间接(信箱) |
| 管道通信 | 共享文件连接,半双工,阻塞机制 |
| 信号 | 事件通知机制,内核态→用户态时处理 |
IPC方式对比
| 方式 | 速度 | 灵活性 | 适用场景 |
|---|---|---|---|
| 共享内存 | 最快 | 高 | 大量数据交换 |
| 消息传递 | 中等 | 最高 | 结构化通信 |
| 管道 | 较快 | 低 | 父子进程/单向数据流 |
| 信号 | 最快 | 低 | 事件通知 |
考研/期末常见考点
- 三种IPC方式的原理和特点
- 管道通信的5个特点(半双工、互斥、阻塞等)
- 直接通信 vs 间接通信
- 基于存储区 vs 基于数据结构的共享
- 信号的处理时机和规则
思考题
- 为什么共享存储需要同步互斥机制?
- 管道通信中,数据被读取后为什么就消失了?
- 直接通信和间接通信各有什么优缺点?
上一篇:OS笔记(三):进程控制 下一篇:OS笔记(五):线程
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐
1
OS笔记(三):进程控制
操作系统 深入理解操作系统中原语的概念、进程的创建/终止/阻塞/唤醒/切换机制,以及Linux中的进程管理实践
2
OS笔记(一):进程与线程简介
操作系统 深入理解操作系统中进程与线程的概念、组成、特征,以及它们在Linux系统中的实际表现
3
OS笔记(二):进程的状态与转换
操作系统 深入理解操作系统中进程的五种状态、状态转换条件,以及在Linux中如何观察进程状态
4
OS笔记(五):线程
操作系统 深入理解操作系统中线程的概念、实现方式、多线程模型,以及Linux线程管理实践
5
OS笔记(六):调度的概念、层次
操作系统 深入理解操作系统中调度的三个层次、七状态模型,以及Linux进程调度机制








