chromium的入口在chrome_initial/app/chrome_exe_main_win.cc文件中。可以在源码中找到入口函数wWinMain,在完成一些初始化工作后,就开始载入chrome.dll,并进入函数ChromeMain函数。以下的代码经过我的简化,只为了能更好的展示程序的主逻辑。其中chromium有一种模式叫metro_mode_,这应该是windows 8新的界面显示模式,在这里我把它忽略了,等有需要的时候再回来慢慢研究。
const wchar_t kChromeDll[] = L"chrome.dll";
HMODULE MainDllLoader::Load(base::string16* version,
base::string16* out_file) {
const wchar_t* dll_name = installer::kChromeDll;
const bool pre_read = true;
HMODULE dll = LoadModuleWithDirectory(out_file, dll_name, pre_read);
return dll;
}
int MainDllLoader::Launch(HINSTANCE instance) {
dll_ = Load(&version, &file);
DLL_MAIN chrome_main =
reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain"));
int rc = chrome_main(instance, &sandbox_info);
}
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
MainDllLoader* loader = MakeMainDllLoader();
int rc = loader->Launch(instance);
}
在进入ChromeMain函数后,接下来还有一系列的调用,其中RunNamedProcessTypeMain中定义了一个数组kMainFunctions,它会根据启动进程传入的参数,确定进程对应的主函数。没有进行指定时,进程对应的默认函数则是BrowserMain。在BrowserMain中创建BrowserMainRunner对象,然后进行初始化和运行。
进入BrowserMainRunner的定义,我们发现它是一个接口类,具体的实现由BrowserMainRunnerImpl完成,它包含了一个BrowserMainLoop对象,通过它管理进程中的线程,如main_thread、db_thread 、file_thread。BrowserMainLoop的实例化在BrowserMain的Initialize中完成,同时在Initialize函数里,会通过MainMessageLoopStart启运主线程,并通过CreateStartupTasks启动其它的线程。CreateStartupTasks中把PreCreateThreads、CreateThreads、BrowserThreadsStarted、PreMainMessageLoopRun这几个函数包装成tasks,放到主线程的消息队列中运行。
CreateThreads函数完成其它线程的创建,这些线程的ID分别为DB、FILE、FILE_USER_BLOCKING、PROCESS_LAUNCHER、CACHE和IO。根据不同的线程用途,会有不同的消息循环,例如:TYPE_UI对应MessagePumpForUI、TYPE_IO对应MessagePumpForIO,默认为MessagePumpDefault,这些会在另一个博文中进行说明。创建线程的过程如下:
在new完一个线程实例后,调用StartWithOptions来启动线程,上文中我们也提到过每一个线程,其实都对应的一个消息循环MessageLoop,在完成MessageLoop的初始化后,会返回Thread一个信号,表示线程已经创建完成,然后线程开始运行消息循环。当需要退出线程时,只需要给线程标记一个flag,当循环中检测到flag时,会退出消息循环,线程结束。