在Chrome的多进程模型里面,有一个主进程和多个辅助进程。主进程Browser负责处理chrome的大部分工作,并且负责创建和销毁其他辅助进程,辅助进程称为Renderer进程,他们主要负责页面的显示工作。每个Renderer进程对应一个或者多个页面或者说站点。下面是Chrome主页上的一张进程模型图。很形象的展示了Chrome的多进程模型。
一般的,WINDOWS下面的应用程序以单进程的方式工作,为什么Chrome要采用多进程方式。在官方文档里面解释的很清楚:谷歌们认为如今的浏览器有点类似于早期的单用户多任务操作系统,一个插件产生的异常就能导致整个浏览器以及它所打开的多有网页标签的崩溃。因此,谷歌决定让不同的页面运行在不同的进程上,这样某个页面产生的异常只会导致这个页面的崩溃,但是不会影响到其他页面和整个浏览器的工作。
通过这个图我们可以很清楚的看到Browser进程又包括了多个线程,至少有一个MainThread和一个I/O Thread 。
创建主线程的代码如下:
void BrowserMainParts::MainMessageLoopStart() {
PreMainMessageLoopStart();
main_message_loop_.reset(new MessageLoop(MessageLoop::TYPE_UI));
// TODO(viettrungluu): should these really go before setting the thread name?
system_monitor_.reset(new SystemMonitor);
hi_res_timer_manager_.reset(new HighResolutionTimerManager);
network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
InitializeMainThread();
PostMainMessageLoopStart();
}
分析一下这段代码。首先创建一个MessageLoop的对象,MessageLoop在构造函数中会把指向自己的指针保持在当前线程的TLS中,如下:
lazy_tls_ptr.Pointer()->Set(this);
以后很多地方会用到这个东西,比如很多IO线程的回调函数调用的时候会获取这个指针来判断自己是否运行在IO线程上,如果不是则会触发异常,构造函数同时设置了线程的类型值。
接下来做的工作是初始化系统监视对象和network_change_notifier_对象。
接着开始初始化MainThread,这里调用的是 main_thread_.reset(new BrowserThread(BrowserThread::UI, MessageLoop::current())),创建了一个对应当前住线程的对象,到这里所有的工作就结束了,而主线程的消息循环要到主窗口建立之后才启动,调用的是RunUIMessageLoop(browser_process.get());
同时,在BrowserProcess中还创建了RendererProcessHost对象,每个RendererProcessHost对应一个RendererProcess,RendererProcess中还包含多个RendererViewHost对象,每个RendererViewHost对应RendererProcess中的一个RenderView对象,RenderView对应这用户可见的页面标签。RendererProcess主要的责任就是使用web渲染引擎来显示html页面,目前谷歌使用的webkit和v8双重引擎来渲染页面,从28开始,将会换成Blink引擎。从图中的关系可以看出来一个RendererProcess同时管理着多个页面的渲染工作。RendererProcess本身没有网络通信功能,如果RendererProcess的引擎需要数据,必须通过进程间通信从BrowserProcess那里获取。而主进程中的RendererProcessHost就是用来同一个确定的RendererProcess建立联系的,每个RendererProcessHost同RendererProcess之间通过一个Channel建立了固定的联系,一直维持到RendererProcess被销毁。Channel在底层使用的是命名管道的机制,以后再专门分析这个进程间通信机制。
BrowserProcess还有一个IO线程。负责所有的网络通信和进程间通信。每个RendererProcess产生的数据请求在主进程排序之后会交给IO进程,IO进程中包含一个ResourceDispatcherHost。网络请求经过ResourceDispatcherHost处理之后再通过底层的网络套接口发给web服务器。
官方设计文档在这里:http://dev.chromium.org/developers/design-documents/multi-process-architecture