概述
由于不同的进程在运行过程中处于不同的用户空间,无法相互感知,因此就诞生 IPC
;信息的传播需要介质,几种跨进程通信的机制就是使用了不同的介质,由于介质的不同,所以传输的方式,传输的频率、传输的数据和适用范围都有不同;
文件
放在物理磁盘上的文件作为不同进程都能访问到的东西,可以作为介质;
优点:
- 操作简单
缺点:
- 通信效率太低
内存
使用文件作为IPC
介质,效率实在太低,太多时间耗费在 IO 上;因此可以选用内存作为传输介质;
管道
虽然操作一个在磁盘上的文件很慢,但是操作一个在内存里的文件很快;
管道
就是一个在内存里的文件,它在内核空间里开辟了一段内存,然后把对这段内存的读写封装为文件操作,既保留了文件操作的简单性,又保留了内存访问的快速;
当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。
当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。
当两个进程都终结的时候,管道也自动消失。
优点:
- 操作简单,读写快速;
缺点:
- 缺少同步机制,读写无法互斥;
- 传输数据有大小限制;
- 一次读写发生四次拷贝,系统调用过多;
消息队列
顾名思义,消息队列
就是要传输的信息以特定格式封装为消息
,然后以链表的方式存放在内核空间;
消息格式:
struct msgbuf{
long mtype;//消息类型(>0)
char mtext[128];//消息文本
};
优点:
- 消息内容独立于进程,进程消失,消息队列的内容也不会删除;
- 消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按照消息的类型读取;
- 我们可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题;
缺点:
- 消息内容有长度限制;
- 消息队列的长度也有限制;
- 一次读写发生四次拷贝,系统调用过多;
共享内存
上面所说的管道和消息队列各有优劣,但是都有一个同样的缺点:一次读写发生四次拷贝,系统调用过多;
这是由于数据需要从用户态转移到内核态,额外发生了一次拷贝;针对这样的高效场景,共享内存
通过把两个进程的一段内存空间映射到同一段物理内存;
网络
UNIX Domain Socket
Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信。socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
UNIX domain socket 是全双工的,API 接口语义丰富,相比其它 IPC 机制有明显的优越性,目前已成为使用最广泛的 IPC 机制,比如 X Window 服务器和 GUI 程序之间就是通过 UNIX domain socket 通讯的。
Unix domain socket 是 POSIX 标准中的一个组件,所以不要被名字迷惑,linux 系统也是支持它的。
Network Socket
和 UNIX Domain Socket
类似,但是它是以 TCP/IP
协议为基础的;
RPC
Remote Procedure Call
远程过程调用,有以下几个特点:
- 屏蔽了网络调用的具体细节,调用远程方法对于开发者来说就像是调用本地方法一样;
- 使用自定义的 TCP 协议,可以让请求报文体积更小,或者使用 HTTP2 协议,也可以很好的减少报文的体积,提高传输效率。
- RPC 实现需要实现编码,序列化,网络传输等。