Chrome的启动流程 之二

 Chrome启动流程 之二

本文主要分析chrome.dll中的ChromeMain函数。

  1. DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
  2.                                  sandbox::SandboxInterfaceInfo* sandbox_info,
  3.                                  TCHAR* command_line) {
  4. #elif defined(OS_POSIX)
  5. int ChromeMain(int argc, const char** argv) {
  6. #endif
  7. #if defined(OS_MACOSX)
  8.   // If Breakpad is not present then turn off os crash dumps so we don't have
  9.   // to wait eons for Apple's Crash Reporter to generate a dump.
  10.   if (IsCrashReporterDisabled()) {
  11.     DebugUtil::DisableOSCrashDumps();
  12.   }
  13. #endif
  14.   RegisterInvalidParamHandler();
  15.   // The exit manager is in charge of calling the dtors of singleton objects.
  16.   base::AtExitManager exit_manager;
  17.   // We need this pool for all the objects created before we get to the
  18.   // event loop, but we don't want to leave them hanging around until the
  19.   // app quits. Each "main" needs to flush this pool right before it goes into
  20.   // its main event loop to get rid of the cruft.
  21.   base::ScopedNSAutoreleasePool autorelease_pool;
  22. #if defined(OS_POSIX)
  23.   base::GlobalDescriptors* g_fds = Singleton<base::GlobalDescriptors>::get();
  24.   g_fds->Set(kPrimaryIPCChannel,
  25.              kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
  26. #if defined(OS_LINUX)
  27.   g_fds->Set(kCrashDumpSignal,
  28.              kCrashDumpSignal + base::GlobalDescriptors::kBaseDescriptor);
  29. #endif
  30. #endif
  31.   // Initialize the command line.
  32. #if defined(OS_WIN)
  33.   CommandLine::Init(0, NULL);
  34. #else
  35.   CommandLine::Init(argc, argv);
  36. #endif
  37. #if defined(OS_MACOSX)
  38.   // Needs to be called after CommandLine::Init().
  39.   InitCrashProcessInfo();
  40. #endif
  41.   const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
  42. #if defined(OS_WIN)
  43.   // Must do this before any other usage of command line!
  44.   if (HasDeprecatedArguments(parsed_command_line.command_line_string()))
  45.     return 1;
  46. #endif
  47. #if defined(OS_POSIX)
  48.   // Always ignore SIGPIPE.  We check the return value of write().
  49.   CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR);
  50. #endif  // OS_POSIX
  51.   int browser_pid;
  52.   std::wstring process_type =
  53.     parsed_command_line.GetSwitchValue(switches::kProcessType);
  54.   if (process_type.empty()) {
  55.     browser_pid = base::GetCurrentProcId();
  56.   } else {
  57. #if defined(OS_WIN)
  58.     std::wstring channel_name =
  59.       parsed_command_line.GetSwitchValue(switches::kProcessChannelID);
  60.     browser_pid = StringToInt(WideToASCII(channel_name));
  61.     DCHECK(browser_pid != 0);
  62. #else
  63.     browser_pid = base::GetCurrentProcId();
  64. #endif
  65. #if defined(OS_POSIX)
  66.     // When you hit Ctrl-C in a terminal running the browser
  67.     // process, a SIGINT is delivered to the entire process group.
  68.     // When debugging the browser process via gdb, gdb catches the
  69.     // SIGINT for the browser process (and dumps you back to the gdb
  70.     // console) but doesn't for the child processes, killing them.
  71.     // The fix is to have child processes ignore SIGINT; they'll die
  72.     // on their own when the browser process goes away.
  73.     // Note that we *can't* rely on DebugUtil::BeingDebugged to catch this
  74.     // case because we are the child process, which is not being debugged.
  75.     if (!DebugUtil::BeingDebugged())
  76.       signal(SIGINT, SIG_IGN);
  77. #endif
  78.   }
  79.   SetupCRT(parsed_command_line);
  80.   // Initialize the Chrome path provider.
  81.   app::RegisterPathProvider();
  82.   chrome::RegisterPathProvider();
  83.   // Initialize the Stats Counters table.  With this initialized,
  84.   // the StatsViewer can be utilized to read counters outside of
  85.   // Chrome.  These lines can be commented out to effectively turn
  86.   // counters 'off'.  The table is created and exists for the life
  87.   // of the process.  It is not cleaned up.
  88.   // TODO(port): we probably need to shut this down correctly to avoid
  89.   // leaking shared memory regions on posix platforms.
  90.   if (parsed_command_line.HasSwitch(switches::kEnableStatsTable)) {
  91.     std::string statsfile =
  92.         StringPrintf("%s-%d", chrome::kStatsFilename, browser_pid);
  93.     StatsTable *stats_table = new StatsTable(statsfile,
  94.         chrome::kStatsMaxThreads, chrome::kStatsMaxCounters);
  95.     StatsTable::set_current(stats_table);
  96.   }
  97.   StatsScope<StatsCounterTimer>
  98.       startup_timer(chrome::Counters::chrome_main());
  99.   // Enable the heap profiler as early as possible!
  100.   EnableHeapProfiler(parsed_command_line);
  101.   // Enable Message Loop related state asap.
  102.   if (parsed_command_line.HasSwitch(switches::kMessageLoopHistogrammer))
  103.     MessageLoop::EnableHistogrammer(true);
  104.   // Checks if the sandbox is enabled in this process and initializes it if this
  105.   // is the case. The crash handler depends on this so it has to be done before
  106.   // its initialization.
  107.   SandboxInitWrapper sandbox_wrapper;
  108. #if defined(OS_WIN)
  109.   sandbox_wrapper.SetServices(sandbox_info);
  110. #endif
  111.   sandbox_wrapper.InitializeSandbox(parsed_command_line, process_type);
  112. #if defined(OS_WIN)
  113.   _Module.Init(NULL, instance);
  114. #endif
  115.   // Notice a user data directory override if any
  116.   const std::wstring user_data_dir =
  117.       parsed_command_line.GetSwitchValue(switches::kUserDataDir);
  118.   if (!user_data_dir.empty())
  119.     CHECK(PathService::Override(chrome::DIR_USER_DATA, user_data_dir));
  120.   bool single_process =
  121. #if defined (GOOGLE_CHROME_BUILD)
  122.     // This is an unsupported and not fully tested mode, so don't enable it for
  123.     // official Chrome builds.
  124.     false;
  125. #else
  126.     parsed_command_line.HasSwitch(switches::kSingleProcess);
  127. #endif
  128.   if (single_process)
  129.     RenderProcessHost::set_run_renderer_in_process(true);
  130. #if defined(OS_MACOSX)
  131.   // TODO(port-mac): This is from renderer_main_platform_delegate.cc.
  132.   // shess tried to refactor things appropriately, but it sprawled out
  133.   // of control because different platforms needed different styles of
  134.   // initialization.  Try again once we understand the process
  135.   // architecture needed and where it should live.
  136.   if (single_process)
  137.     InitWebCoreSystemInterface();
  138. #endif
  139.   bool icu_result = icu_util::Initialize();
  140.   CHECK(icu_result);
  141.   logging::OldFileDeletionState file_state =
  142.       logging::APPEND_TO_OLD_LOG_FILE;
  143.   if (process_type.empty()) {
  144.     file_state = logging::DELETE_OLD_LOG_FILE;
  145.   }
  146.   logging::InitChromeLogging(parsed_command_line, file_state);
  147. #ifdef NDEBUG
  148.   if (parsed_command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
  149.       parsed_command_line.HasSwitch(switches::kEnableDCHECK)) {
  150. #if defined(OS_WIN)
  151.     logging::SetLogReportHandler(ChromeAssert);
  152. #endif
  153.   }
  154. #endif  // NDEBUG
  155.   if (!process_type.empty())
  156.     CommonSubprocessInit();
  157.   startup_timer.Stop();  // End of Startup Time Measurement.
  158.   MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
  159.                                  &autorelease_pool);
  160.   // TODO(port): turn on these main() functions as they've been de-winified.
  161.   int rv = -1;
  162.   if (process_type == switches::kRendererProcess) {
  163.     rv = RendererMain(main_params);
  164.   } else if (process_type == switches::kPluginProcess) {
  165.     rv = PluginMain(main_params);
  166.   } else if (process_type == switches::kUtilityProcess) {
  167.     rv = UtilityMain(main_params);
  168.   } else if (process_type == switches::kWorkerProcess) {
  169. #if defined(OS_WIN)
  170.     rv = WorkerMain(main_params);
  171. #else
  172.     NOTIMPLEMENTED();
  173. #endif
  174.   } else if (process_type == switches::kZygoteProcess) {
  175. #if defined(OS_LINUX)
  176.     if (ZygoteMain(main_params)) {
  177.       // Zygote::HandleForkRequest may have reallocated the command
  178.       // line so update it here with the new version.
  179.       const CommandLine& parsed_command_line =
  180.         *CommandLine::ForCurrentProcess();
  181.       MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
  182.                                      &autorelease_pool);
  183.       RendererMain(main_params);
  184.     }
  185. #else
  186.     NOTIMPLEMENTED();
  187. #endif
  188.   } else if (process_type.empty()) {
  189. #if defined(OS_LINUX)
  190.     // Glib type system initialization. Needed at least for gconf,
  191.     // used in net/proxy/proxy_config_service_linux.cc. Most likely
  192.     // this is superfluous as gtk_init() ought to do this. It's
  193.     // definitely harmless, so retained as a reminder of this
  194.     // requirement for gconf.
  195.     g_type_init();
  196.     // gtk_init() can change |argc| and |argv|, but nobody else uses them.
  197.     gtk_init(&argc, const_cast<char***>(&argv));
  198.     SetUpGLibLogHandler();
  199. #endif
  200.     ScopedOleInitializer ole_initializer;
  201.     rv = BrowserMain(main_params);
  202.   } else {
  203.     NOTREACHED() << "Unknown process type";
  204.   }
  205.   if (!process_type.empty()) {
  206.     ResourceBundle::CleanupSharedInstance();
  207.   }
  208. #if defined(OS_WIN)
  209. #ifdef _CRTDBG_MAP_ALLOC
  210.   _CrtDumpMemoryLeaks();
  211. #endif  // _CRTDBG_MAP_ALLOC
  212.   _Module.Term();
  213. #endif
  214.   logging::CleanupChromeLogging();
  215.   return rv;
  216. }

 

Line 15  RegisterInvalidParamHandler();

主要是注册一些回调函数,用于调试和定位(后续采用在代码中增加一些中文注释的方法来解释)

  1. void RegisterInvalidParamHandler() {
  2. #if defined(OS_WIN)
  3.     //当调用CRT函数时,参数不合法时,将调用InvalidParameter函数
  4.     //InvalidParameter函数也就是产生中断,触发CrashReport服务
  5.   _set_invalid_parameter_handler(InvalidParameter);
  6.   //当系统调用纯虚函数时,将调用PureCall函数,用于调试
  7.   _set_purecall_handler(PureCall);
  8.   // Gather allocation failure.
  9.   //当内存分配失败时,将调用OnNoMemory,
  10.   std::set_new_handler(&OnNoMemory);
  11.   // Also enable the new handler for malloc() based failures.
  12.   //支持Malloc模式
  13.   _set_new_mode(1);
  14. #endif
  15. }

 

Line 50 -- Line54可以不用关注,主要是为了规避早期Chrome的一个BUG而已。

LIne61 -- Line 75主要是获取当前Browser进程的ID。因为当前启动的是Browser进程,所以获取的肯定是Browser ID。

Line 91 设置CRT参数,比较简单。

Line 94 -- Line 95 主要初始化各种路径辅助类PathService参数。该类主要提供各种路径服务,比如获取当前目录,用户数据存储目录等服务。

Line 103 -- Line110 当启动参数中包含了 --enable-stats-table时,将初始化状态统计表辅助类,用于统计线程数量。

Line 112 -- Line 114 初始化状态统机辅助类StatsCounterTimer,该类将会启动一个计数器,在这里主要统计本函数所花时间。

Line 116   EnableHeapProfiler(parsed_command_line); 加载memory_watcher.dll,Chrome中的一个辅助类,用于统计chrome的内存占用情况。在Chrome中按下Shift + Esc可以查看内存情况,在后面就是memory_watch.dll起作用。

 

Chrome 内存查看器

Line 119 -- Line120 当Chrome启动模式指定了message-loop-histogrammer模式时,用于启动线程消息频率统计功能,当在浏览器地址栏输入about:histograms/Loop时,可以查看到效果(前提是以message-loop-histogrammer模式启动,缺省情况下是不会启动的)。
Chrome Message loop histograms
Line 125 -- Line 133 主要是初始化SandBox服务。Chrome的Crash Report服务依赖于SandBox业务,所以这个服务需要尽早启动,保证Crash Report功能有效。
Line 135 -- Line 139 如果启动时参数中用户指定了用户数据目录,则在PathService类中替换用户数据目录为用户制定的目录。
Line 141 -- Line 159 检测启动参数是否包含了--single-process参数,如果包含了该参数,则采用单进程模式,Renderer也将包含在Browser进程中。下面这两幅图可以明显的看出在两种进程模式下的进程情况。相关的进程模式可以参考另外一篇文章(尚未发出),也可参考Chrome的 官方网站说明
Chrome单进程模式
单进程模式下的进程模式(所有页面都在同一进程中,与FireFox,IE一样模式)

Chrome缺省进程模式
缺省模式下的进程模式(每一个网站实例一个进程)
Line 161 -- Line 162 初始化Unicode语言库。IBM提供的一个多语言支持库,比较大。
Line 164 -- Line 169 初始化LOG库,涉及到一个重新启动Chrome时是否删除旧的LOG选项。
process_type这个参数,在缺省情况下,都是为brower进程,但是在启动时也可以指定当前进程类型为Renderer、Plugin、Utility、Worker。这个主要通过启动参数--type=XXX来指定( 这里还不是很清楚,后续搞清楚后再更新)。
Line 180 -- Line 245 主要根据不同的进程类型(process_type),调用下一步的初始化过程。在缺省情况下(不指定type参数),将会执行下一个函数BrowserMain,那将是一个更复杂一些的函数。

总结一下,在本函数中,主要也是初始化一些辅助库、全局参数等,相对起来比较好理解。
到目前为止,应该说还没有进入正题,Chrome的两个核心进程Browser和Renderer的初始化工作还没有开始。













 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值