知识全景图/ 软件工程与系统/ 如何设计系统/ 如何设计操作系统/ IPC 与同步

如何设计 IPC 与同步

让相互隔离的进程能安全协作,同时不把共享状态写乱。

定位:虚拟内存把进程隔离开了,但系统又需要它们协作。IPC 解决“怎么传消息”,同步解决“共享状态谁先改、谁等待、谁唤醒”。
一、坏场景:隔离成功后,进程反而无法协作
失败:shell 想把输出交给 grep,服务进程想把结果交给客户端,父进程想等子进程结束。没有 IPC,进程之间只能互不相干;如果直接共享内存,又会互相写乱。
协作需求直接做会怎样坏被迫设计
一个进程把字节流交给另一个进程直接共享缓冲区会越界、覆盖、丢数据pipe
父进程等待子进程结束忙等浪费 CPU,状态可能错过wait / wakeup
多个进程共享一段状态同时写导致状态撕裂锁、信号量、条件变量
内核和驱动共享队列中断和进程上下文并发修改队列关中断区、spinlock、队列协议
二、第一版 IPC 先做 pipe
对象字段负责什么
Pipebuffer、read_pos、write_pos、closed_read、closed_write保存进程间字节流
PipeReaderpipe、offset、flags读端 fd 引用
PipeWriterpipe、offset、flags写端 fd 引用
WaitQueuewaiting_processes、condition读空、写满时阻塞和唤醒
pipe_write(pipe, bytes): while pipe.buffer.full: sleep(pipe.write_wait_queue) pipe.buffer.push(bytes) wakeup(pipe.read_wait_queue) pipe_read(pipe, len): while pipe.buffer.empty and !pipe.closed_write: sleep(pipe.read_wait_queue) data = pipe.buffer.pop(len) wakeup(pipe.write_wait_queue) return data
三、同步的核心不是锁,而是等待条件
机制解决什么最小规则
mutex同一时刻只有一个执行流修改共享状态持锁时间短,退出路径必须释放
semaphore有限数量资源的占用与释放计数不能负,释放要唤醒等待者
condition variable等待某个状态变成真检查条件和 sleep 必须原子衔接
wait queue把进程挂到等待条件上wakeup 要对应具体条件,不要乱唤醒
关键点:同步不是“加锁”这么简单。真正难的是:条件什么时候成立,等待者什么时候睡,谁负责唤醒,失败时怎么不丢唤醒。
四、常见失败要先验收
失败原因设计防线
丢唤醒检查条件和睡眠不是原子过程在锁保护下检查条件并进入 wait queue
死锁两个进程互相等待对方持有的锁固定锁顺序,禁止持锁等待外部事件
饥饿某个等待者长期拿不到资源等待队列 FIFO 或公平策略
优先级反转低优先级持锁阻塞高优先级第一版先记录风险,第二版再做继承
五、验收实验
实验通过标准证明了什么
pipe 字节流A 写入,B 按顺序读出IPC 数据传递成立
读空阻塞pipe 空时 read 睡眠,write 后被唤醒wait / wakeup 成立
写满阻塞pipe 满时 write 睡眠,read 后恢复背压成立
锁保护多进程递增共享计数,结果不丢增量互斥成立
关闭语义写端关闭后,读端读完剩余数据返回 EOF引用与生命周期成立
六、回到操作系统主线
下一页:网络与 Socket
pipe 是本机进程间通信,socket 则把 fd 延伸到网络连接。继续看 如何设计网络与 Socket
回总页
一句话:IPC 与同步不是为了炫技,而是让隔离后的进程重新协作,并且协作时不丢数据、不乱状态、不睡死。