关于Chrome的线程模型,在他的开发文档中有专门的介绍,原文地址在这里:http://dev.chromium.org/developers/design-documents/threading
chrome的进程,chrome没有采用一般应用程序的单进程多线程的模型,而是采用了多进程的模型,按照他的文字说明,主界面框架下的一个TAB就对应这个一个进程。但实际上,一个进程不仅仅包含一个页面,实际上同类的页面在共用一个进程。
chrome进程模型下有2种进程,一个是Browser进程。另一种是Renderer进程,Browser只有一个,主控整个系统的运行,而Renderer则可以有多个,主要负责页面的渲染和显示。
Browser作为主进程最先启动,Browser包含一个主线程mainthread,在mainthread中对整个系统进行初始化,并启动为另外几个线程,看下面的代码:
void CreateChildThreads(BrowserProcessImpl* process) {
process->db_thread();
process->file_thread();
process->process_launcher_thread();
process->cache_thread();
process->io_thread();
}
db_thread线程负责数据库处理,file_thread负责文件管理,cache_thread负责管理缓存。io_thread则负责管理进程间通信和所有I/O行为。
这其中,io_thread不仅负责Browser进程的I/O,而且其他Renderer的I/O请求也会通过进程间通信发送到这个线程,由该线程进行处理,最后把结果在返回给各个Renderer进程。各个线程的功能不一样,但设计模式是一样的,下面重点分析一下io_thread的初始化和执行流程。
线程的创建在BrowserProcessImpl的CreateIOThread中实现,代码如下:
void BrowserProcessImpl::CreateIOThread() {
先创建一个IOThread的实例,然后设置此线程的类型为TYPE_IO,接着,调用StartWithOptions启动这个线程。
StartWithOptions函数首先是保存传递进来的Options,接着通过PlatformThread::Create来创建线程,这里PlatformThread类的作用是支持不同系统平台的线程的创建。然后调用startup_data.event.Wait()来等待此线程的消息循环的启动,这表明只有消息循环启动之后,整个函数才能返回。
在PlatformThread::Create很简单,调用系统APICreateThread,线程函数是ThreadFunc,传递给线程函数的参数就是IOThread对象本身的指针。
ThreadFunc也很简单,之后调用Thread的成员ThreadMain, 所以ThreadMain才是线程的主函数。
下面详细分析一下ThreadMain,首先定义一个MessageLoop类的对象,并把之前保存的类型赋予这个对象。接着调用IOThread的Init进行基本的初始化动作,然后调用startup_data_->event.Signal(),让线程处于未置信状态。最后调用MessageLoop的Run进入无限的消息循环,直到接到退出消息循环的命令,此时线程也要结束了。这是一般windows线程的常用方式,只不过chrome对其进行了一定的封装,并且把定义了几种不同的消息循环。
在MessageLoop中有一个枚举变量有如下定义:
enum Type {
TYPE_DEFAULT,
TYPE_UI,
TYPE_IO
};
可见总共有3种不同的消息循环。
MessageLoopForUI::Run(Dispatcher* dispatcher);
void MessageLoop::RunHandler()