761 字
4 分钟
进程间通信方式:管道、消息队列、共享内存、信号量与套接字
进程之间的通信方式主要有:管道、消息队列、共享内存、信号量、信号、套接字。
- 管道:最简单的 IPC 方式,数据从一端写入、另一端读出,单向流动。匿名管道只能用于有亲缘关系的进程(如父子进程)。
- 消息队列:允许进程发送和接收带类型的消息,消息在队列里排队,接收方可以按类型选择性地读取。比管道灵活,但每条消息有大小限制。
- 共享内存:最快的 IPC 方式,多个进程直接读写同一块物理内存,不需要数据拷贝。必须配合信号量或互斥锁使用,否则会出现竞态条件。
- 信号量:本身不传递数据,是用来同步的,可以控制多个进程对共享资源的访问顺序。
- 信号:一种异步通知机制,用来告诉进程发生了某个事件。
- 套接字:最灵活,既能在本机进程间通信,也能跨网络通信。网络套接字用 TCP/UDP 协议,是分布式系统通信的基础。
为什么说共享内存最快?快多少?
快在不需要数据拷贝。管道和消息队列都要把数据从用户空间拷到内核空间,再从内核空间拷到另一个进程的用户空间,两次拷贝。共享内存是多个进程的页表直接指向同一块物理内存,写进去立刻就能被另一个进程看到,CPU 不用搬运数据。
实际项目中什么时候用管道,什么时候用共享内存?
数据量小、通信不频繁就用管道,简单省事。比如主进程 fork 出子进程执行命令,通过管道拿结果,几百字节的事,用管道就够了。
数据量大、通信频繁就用共享内存,比如视频处理软件,解码进程和渲染进程之间每秒传几十帧画面。
跨机器的进程通信一般用什么方案?
跨机器只能走网络,底层都是 Socket。但直接用 Socket 编程太麻烦了,一般都用封装好的框架:
- 同步调用可以用 RPC 框架,比如 gRPC。
- 异步通信可以用消息队列,比如 Kafka、RocketMQ、RabbitMQ。
- 微服务之间互相调用基本都是 HTTP 或者 gRPC。
选择主要看场景:需要实时响应用 RPC;允许延迟、需要削峰填谷用消息队列。
信号和信号量有什么区别?
信号是异步通知机制,一个进程给另一个进程发个信号,信号不能传递数据,就是一个编号。
信号量本身不传递数据,是用来同步的,可以控制多个进程对共享资源的访问顺序。本质是个计数器,P 操作减一,V 操作加一,减到 0 就阻塞。典型用法是保护共享内存,或者实现生产者消费者模型。
进程间通信方式:管道、消息队列、共享内存、信号量与套接字
https://blog.xqcherry.top/posts/interview/operating-system/ipc-ways/ 目录