进程间通信的本质是让 不同的进程看到同一份资源(内存 , 文件,内核缓冲等),也就是数据拷贝
前提知识:每个进程都有自己的用户空间,而内核空间是每个进程共享的。因此进程之间想要进行通信,就需要通过内核来实现。
1.进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程(cat log.txt | grep hello)
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变
2.进程间通信方式
1.管道
管道本质上就是内核中的一个缓存,是最简单,效率最差的一种通信方式。
缺点:
- 半双工通信,一个管道只能一个进程写一个进程读,效率低。
2.消息队列
消息队列可以解决管道通信效率低,不适合进程间频繁交换数据的问题;
缺点:
- 每一个消息体有最大长度的限制
- 消息队列通信过程中存在用户态和内核态之间的数据拷贝问题
3.共享内存
共享内存可以解决消息队列通信存在的用户态和内核态之间数据拷贝的问题;不同的进程拿出一块虚拟内存空间,映射到相同的物理内存空间。这样一个进程写入的东西,另一个进程马上就能够看到,不需要进行拷贝。
缺点:
- 若多个进程同时往共享内存中写数据,内容可能会被覆盖
4.信号量
信号量就是一种解决共享内存内容覆盖问题的保护机制;
信号量本质上是一个整型计数器,用于实现进程间的互斥和同步;
信号量代表着资源的数量;
信号量是使用P、V操作来实现的。
5.信号
6.Socket
前面提到的管道,消息队列,共享内存,信号量和信号都是在同一台主机上进行进程间通信,如果想要跨网络和不同主机上的进程进行通信,则需要用到socket。当然在同一主机上进行进程间通信也是没问题的。
注意:Socket是操作系统提供给程序员操作网络的接口,根据底层不同的实现方式,通信方式也不同。
- 针对TCP的Socket通信:
- 针对UDP的Socket通信: