ipcz 是chromium的跨进程通信系统。z可能是代表zero,表示0拷贝通信。
chromium的文档是非常丰富的,关于ipcz最重要的一篇官方文档是IPCZ。
关于ipcz本篇文章主要的目的是通过源代码去分析它的实现。再进入分析前我们先对官方文档做一个总结,来说明ipcz的能力。 ipcz和一般的ipc系统不同主要有点个方面
- 0拷贝通信
- 消除代理能力
0拷贝通信比较简单,消除代理能力是什么意思呢?
考虑这样一个场景, 有a,b,c三个进程通信,a和b之间存在链接,b和c之间存在连接,那么a要和c通信,只能通过b进行代理。这显然造成了一定性能损失和资源浪费。 在ipcz系统中,如果b发现自己是代理节点,可以帮助a和c直接建立链接来消除代理。
显然ipcz的设计初衷就是要建立一个类似ip协议的路由网络能力。
ipcz的整体结构图如下:
一般进程里面有一个Node节点, 用NodeLink记录两个Node的连接(用于找到对端)。 使用Driver Transport 表示一个传输点,也就是维护Node 之间的通信通道(一般是socket链接)。 两个Node内可以有多个子链接,每个子链接的端点为Portal, 每个Portal 又对应一个Router, Router的主要作用是对消息进行接收或者转发。两个Router之间的链接用RouterLink表示。 两个Node 之间通信的消息内容都放在一块共享内存上, Driver Transport 只负责传递控制信息,这样来实现0拷贝。
整个进程通信系统中一般有一个Node为Broker节点,在代理消除过程中,为了帮助a和c建立通信链接的,需要第三者来协调,这个第三者需要a和c都能和它通信,在ipcz系统中这样的节点叫Broker Node。Broker Node 是有名节点,其他进程可以通过名字来和它建立通信(一般为有名socket管道)。
一般一个ipcz系统中每个进程对应一个Node,整个系统只有一个Broker Node。
有了对数据结构的基本认识,我们来介绍代理消除。
这里ac通信需要b进行代理,可以通过命令来消除代理:
- B告诉A自己是中间人,并告知C将向A发送直连请求
- B告诉C自己是中间人
- 如果AC没有NodeLink 需要连接Brokers协助a和c之间创建NodeLink(通信管道)
- c借助AC之间的NodeLink创建一个ACx的RouterLink
- C向A发送直连请求, 使用ACx bypass AB1
- 节点A根据节点B提供的信息对该请求进行验证,即该请求来自预期的节点C,并且涉及AB1。然后,节点A通过相应地更新其路由器的链接来满足该请求。
- 后续A和C的通信都通过ACx进行。
注意,AB1和BC5仍然保留着。它们现在被称为衰减链接(decaying links),并将会随着时间的推移逐渐淘汰。
上述代理消除是简单的只有一个代理节点的消除,在存在多个代理节点的情况可能混造成混乱
比如这个例子,D和E通信,A、B、C都是代理节点。 如果A,B,C 同时发现自己是代理节点,请求代理消除,那么会造成混乱,如何解决这个问题?
IPCZ 引入了中心链接和边缘链接的概念,每条路径的生命周期始于两个路由器之间的单个链接。该链接被指定为路径的中央链接,每条路径都只有一个中央链接。其他链接为边缘链接,代理选择绕过的规则很简单:只有在代理路由器与中心链接相邻时,才能绕过代理。 消除代理建立新的连接之后的连接成为新的中心链接。
有个中心链接的概念可以进一步说明代理消除的过程。首先要知道在ipcz中存在向内和向外方向的概念。假如某个消息由某router发出,该消息向中心链接方向移动,则这个消息的方向为向外。 某个消息由某个router 发出,这个消息远离中心链接,则这个消息的方向为向内。
举例如上图:
AB1是中心链接,B router向 A router发送消息为向外方向,通向A向B发送消息为向内方向。
AE0是边缘链接,E router 向A发送消息为向外方向,A router 向E router发送消息为向内方向。
BC5也是边缘链接,B router向C router发送消息为向内方向,C router 向B router 发送消息为向外方向。
同样,路由器B被认为是路由器A的向外对等方,路由器E被认为是路由器A的向内对等方。路由器A是路由器E的向外对等方,路由器E没有向内对等方,因为它是终端路由器。
在启动代理绕过的过程中,代理路由会先通知其向外对等要进行代理消除, 再通知其向内对等提发起代理消除,直接请求broker 建立新的链接。
举例要消除E->A->B 中A代理:
- A告诉B自己是中间人,并告知E将向B发送直连请求
- A告诉E自己是中间人
- 如果EB没有NodeLink 需要连接Brokers协助E和B之间创建NodeLink(通信管道)
- E借助EB之间的NodeLink创建一个EBx的RouterLink
- E向B发送直连请求, 使用EBx bypass AB1 和 AE0
- 节点B根据节点A提供的信息对该请求进行验证,即该请求来自预期的节点E,并且涉及AB
- 然后,节点B通过相应地更新其路由器的链接来满足该请求。
- 后续E和B的通信都通过EBx进行。
本篇文章就到这里,下一篇文章通过代码分析。