Chromium进程间的通信机制浅析(android版本)(一)

一、 综述

Chromium的多进程模型意味着会有频繁的进程间通信,其中主要的IPC方式是命名管道。在遵循posix标准的操作系统中,通过UNIX域套接字来实现命名管道。每个render进程都会分配一个命名管道来与browser进程通信,并且该管道是以异步方式使用,以确保不会因等待而阻塞。

Chrome最主要有三类进程,一类是Browser主进程;各个Render进程;另外还有一类是Plugin进程,每一个插件,在Chrome中都是以进程的形式呈现。Render进程和Plugin进程都与Browser保持进程间的通信,Render进程与Plugin进程之间也有彼此联系的通路,唯独是多个Render进程或多个Plugin进程直接,没有互相联系的途径,全靠Browser协调

Chromium进程间的通信机制浅析(android版本)(一)

在这里先放一张经典结构图,但实际调试中发现与该结构图还是有些许出入:

1.Browser进程中Channel对象在主线程中创建,而不是在IO线程创建

2.创建的是非命名的套接字,而不是命名的套接字(linux下)

3.Render进程也同样存在IO线程和Channel对象,结构与Browser进程类似。

二、 基本原则

1.所有的通信都由Channel类完成,其封装了具体的实现细节。Channel分为Server和Client两种工作模式,分别运行于Browser和Render进程

2.对于Channel类的所有调用都在I/O线程进行,Browser进程如此,Render进程同样如此。

3.为了更简易的使用Channel,Browser进程提供了ChannelProxy类,Render进程提供了SyncChannel类(继承于ChannelProxy)对Channel的操作进行代理。这样在其他线程中调用ChannelProxy中的某个方法,其会将Channel类的相应方法包装成Task,转发到I/O线程中执行。

4.进程间的通信大多是异步的,但存在render-to-browser的同步消息,由SyncChannel类完成。不能在UI线程中处理任何同步消息,必须在IO线程处理。不存在browser-to-render的同步消息。

5.每一个Channel实际上打开了两对相互连接的套接字,一对用于传输普通消息,由server端调用socketpair系统调用来生成。另一对专门用于传递打开的文件描述符,由client端调用socketpair系统调用来生成。

三、 主要对象介绍

1. Channel对象

对底层通信具体实现进行封装,其只是一个外壳,真正的操作被转发到与平台相关的ChannelImpl类来实现。

A.CreatePipe方法:用UNIX域套接字的方式建立两个相互连接的套接字,分为Server端和Client端。有两种建立方式,一种建立有名的UNIX域套接字,用于任意进程间的通信;一种建立无名的UNIX域套接字,仅用于父子进程间通信。

B.ProcessOutgoingMessages方法:由Send方法调用,完成实际的序列化和发送操作。

C.ReadData方法,完成实际的读取字符流的操作

D.AcceptConnection方法:完成连接。设置文件描述符监视者对象的delegate为该ChannelImpl对象,文件描述符监视者对象的相关方法会转发给delegate。Clinet端还需要发送HelloMessage消息,Server端等待该消息。

E.Pipe_:用于传递普通消息的套接字

F.Fd_pipe_:用于传递打开的文件描述符的套接字

2. ChannelProxy对象

对Channel的进一步封装,其主要操作都转发由内部类Context完成。Context中有几个关键的属性:

listener_task_runner_:标识为初始化该ChannelProxy的线程(如UI线程)

ipc_task_runner_:标识为IO线程

listener_:对ChannelProxy的监听者(初始化为构造ChannelProxy的对象,如RrenderProcessHostImpl),没有被过滤的消息最终都转发给该监听者。

filters_:过滤器,很多种类的过滤器,首先对消息进行过滤,被选中的消息被过滤器处理,剩下的转发给监听者。

ChannelProxy的方法会调用到Context的相应方法,其根据ipc_task_runner_的指向,Context的方法在IO线程中执行,并且调用Channel的相应方法。也就是说Context也运行在IO线程,ChannelProxy与Context之间就是UI与IO线程的分界线。

3. ChannelReader对象

对读取的字符流完成反序列化操作,重新组装成消息,转发给其listener(初始化为Channel::Context)处理。这些都由DispatchInputData方法完成。

Context会根据filter_将消息过滤,剩下的根据listener_task_runner_的指向发送回其他线程处理。

4. MessageLoopForIO::FileDescriptorWatcher对象

文件描述符监视者对象,监视特定的文件描述符,该套接字收到的消息会首先由线程处理事件MessagePumpLibevent转发给监视者的相关方法。

基本类图:

Chromium进程间的通信机制浅析(android版本)(一)