进程之间怎么聊天?信号、管道、共享内存、Socket 大乱斗!

------ 小dora 操作系统学习笔记 Vol.5 · 进程通信篇(IPC)


dora:"我创建了两个进程,咋让它们对话?"

操作系统冷冷一笑:"进程是天生孤独的,但我给你桥梁。"

本章目标是:让你轻松理解操作系统中**进程通信(Inter-Process Communication, IPC)**的几种典型方式------信号、管道、共享内存、Socket,并且知道什么时候该用谁,背后又是啥机制。


🧠 一、进程为什么不能直接对话?

操作系统的"内存隔离机制"决定了:

  • 每个进程都有独立的虚拟地址空间
  • 你无法直接访问另一个进程的变量、堆或栈

所以:必须借助操作系统提供的"中介"来通信,这就是 IPC。

📌 巧记口诀:

"进程像独立公寓,交流靠物业搭电梯。"


🔔 二、信号(Signal):最基础的通信方式

信号本质上是一个"异步中断",用于通知进程发生了某个事件。

常见信号:

信号编号 名称 含义
2 SIGINT Ctrl+C 中断
9 SIGKILL 强制杀死进程
15 SIGTERM 请求终止进程
17/18/20 SIGCHLD 子进程退出通知

特点:

  • 轻量级,无需共享资源
  • 通信粒度小,不能传输数据(只能传 signal)

📌 常用于:中断处理、父子进程通知、定时任务

📌 巧记口诀:

"信号像微信提醒,只能告诉你'有事',不能说'啥事'。"


🧵 三、管道(Pipe):标准 I/O 的串联通道

3.1 匿名管道

arduino 复制代码
int pipe(int fd[2]);
  • fd[0]:读端
  • fd[1]:写端

用于具有亲缘关系的进程(如父子)

📌 示例:

shell 复制代码
$ ls | grep .txt

Shell 实际上:

  • fork 出两个子进程
  • 用 pipe 把 ls 的 stdout 和 grep 的 stdin 串起来

📌 特点:

  • 单向
  • 仅限父子进程

3.2 命名管道(FIFO)

bash 复制代码
mkfifo mypipe
  • 可用于任意两个进程(不一定有亲缘关系)
  • 存在于文件系统中,类似设备文件

📌 巧记口诀:

"匿名管道像耳语,只能和亲人讲;命名管道像喇叭,大家都能听。"


🧠 四、共享内存(Shared Memory):最快的通信方式

"你不许动我空间,但我允许你搬来一起住。"

共享内存是多个进程共享一块物理内存区域:

ini 复制代码
int shmid = shmget(key, size, IPC_CREAT);
void* addr = shmat(shmid, NULL, 0);

优点:

  • 不需要数据拷贝(零拷贝)
  • 快到飞起,常用于实时系统、数据库、图像处理

缺点:

  • 不安全,需额外同步机制(信号量、互斥锁)

📌 巧记口诀:

"共享内存像情侣合租,快是快,但吵架频繁要协调。"


⚖️ 五、信号量(Semaphore):共享内存的好搭档

  • 本质:一个整型变量 + PV 操作
  • 用于控制共享资源的访问顺序,避免竞态条件(race condition)
scss 复制代码
sem_wait(&sem);   // P操作,等待资源
sem_post(&sem);   // V操作,释放资源

📌 常与共享内存配合使用

📌 巧记口诀:

"你用锅我用铲,排好队不打架。"


🌐 六、Socket 通信:远程/本地皆可聊

Socket 是最强大的 IPC:

  • 可以进程内通信(UNIX 域 Socket)
  • 也可以跨主机通信(TCP/IP)
scss 复制代码
socket() → bind() → listen() → accept()

或:在 Node.js 中这样写:

ini 复制代码
const net = require('net');
const server = net.createServer(socket => {
  socket.write('hello client');
});
server.listen(8080);

📌 巧记口诀:

"Socket 是全球通,跨城跨国都能通。"


🔍 七、总结对比:选谁好?

方式 是否可跨主机 是否传数据 速度 使用场景
信号 Signal 否 否 快 中断、通知
管道 Pipe 否 ✅ 中 父子、串联任务
共享内存 否 ✅✅ 最快 数据库、实时系统
Socket ✅ ✅ 中等 网络通信、服务端

📌 巧记口诀:

"信号吼一声,管道说一句,内存放全文,Socket 发快递。"


🧪 面试练习题

Q1:进程之间不能直接访问彼此内存的原因?

✅ 答案:虚拟地址空间隔离(保护性设计)


Q2:哪种 IPC 方式最快?为何?

✅ 答案:共享内存;因无需拷贝、直接访问物理页


Q3:Socket 为何可以跨主机?

✅ 答案:基于网络协议栈,使用 IP + 端口通信


Q4:信号量是做什么用的?

✅ 答案:同步访问共享资源,防止竞态条件


✅ 总结:

"进程各自为战,通信靠中介;哪种方式靠谱,还得看场景!"


相关推荐
openEuler社区40 分钟前
openEuler 26.09创新版本发布,深化全场景创新
开源·操作系统·openeuler
云计算练习生1 天前
什么是操作系统的体系结构?宏内核、微内核与外核
操作系统·内核·外核·操作系统结构
流浪0012 天前
Linux系统篇44——线程(九) 互斥锁的接口与原理,从 xchgb 的原子交换说起
linux·操作系统·线程·互斥锁·互斥锁原理
福兮说4 天前
秋招复习操作系统并发,我让 AI 生成了一张知识图谱,15 条关系里改了 5 条
人工智能·操作系统·知识图谱·秋招
流浪0015 天前
Linux系统篇43——线程(八) 线程的数据不一致问题,从 ticket-- 的非原子性说起
linux·操作系统·线程·线程安全·锁
小小小小钰儿7 天前
2.3-云端API集成
人工智能·计算机·网络安全·操作系统·编程
做系统的大强7 天前
脚本说 PASS、OS 读全零 —— 到底是谁在撒谎?
后端·操作系统
小小小小钰儿7 天前
2.2-模型微调
人工智能·深度学习·机器学习·计算机·网络安全·操作系统·编程
小小小小钰儿8 天前
2.1-Windows本地部署大模型
人工智能·windows·计算机·网络安全·操作系统·编程
流浪0019 天前
Linux系统篇39——线程(四) pthread库的由来和线程的创建与等待
linux·操作系统·线程·pthread库