进程间通信 (IPC,InterProcess Communication)
常见的通信方式
- 管道pipe(无名管道):半双工 数据只能单向流动,只能在父子进程间使用。
- 命名管道fifo:半双工 允许无亲缘关系进程间的通信。
- 消息队列:克服了信号传递信息少,管道只能承载无格式字节流、缓冲区大小受限的问题。
- 共享存储:这段共享内存由一个进程创建,多个进程都可以访问。
- 信号量semaphore:信号量是计数器,可以用来控制多个进程对共享资源的访问。
- 套接字:可以用于不同机器间的进程通信。
- 信号(sinal):复杂。用于通知事件发生。
详解
管道
- 无名管道和有名管道,除了建立、打开、删除方式不同,其余几乎一样。都是通过内核缓冲区,实现数据传输。
- 无名管道通过
pipe()
系统调用来创建并打开。 - 命名管道在磁盘上有对应的节点,没有数据块。相当于有名字和相应权限,通过
mknode()
系统调用创建并打开。一旦建立,任何进程通过文件名打开读写,不限于父子进程。没有进程使用的时候,FIFO内存中释放,但磁盘节点一直存在
消息队列
一个消息的链表。保存在内核中。用户进程可以向消息队列添加消息,也可以读取消息。
相比管道,消息队列可以根据自定义条件接收指定消息,不用依次取消息。
共享内存
允许多个线程共享一个存储区。
好处是效率高。进程可以直接读写内存数据,只需要两次数据拷贝:
- 用户空间到内存
- 内存到用户空间
而管道和消息队列,需要在内核和用户空间进行4次数据拷贝: - 由用户空间的buf中将数据拷贝到内核中。
- 内核将数据拷贝到内存中。
- 内存到内核。
- 内核到用户空间的buf
共享内存有两种实现方式:
- 内存映射
- 共享内存机制
信号量
semaphore是一个计数器。
信号量基于PV原子操作,用于实现进程间的互斥和同步。