Chrome原始碼分析之Renderer進程初始化(十五)

來源:互聯網
上載者:User

前面已經分析過,一個RenderProcess與一個主進程中的RenerProcessHost對應。RenderProcess到底在什麼時候建立,答案是在RenerProcessHos初始化的時候建立,對應的過程在BrowserRenderProcessHost::Init函數中實現。我們來看看這個函數,函數對應的檔案是:

src\chrome\browser\renderer_host\browser_render_process_host.cc

Init開始部分做一些準備工作,比如擷取IO線程對象的指標:base::Thread* io_thread = g_browser_process->io_thread();

初始化處理序間通訊訊息過濾對象:

  scoped_refptr<ResourceMessageFilter> resource_message_filter(
      new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(),
                                id(),
                                audio_renderer_host_.get(),
                                PluginService::GetInstance(),
                                g_browser_process->print_job_manager(),
                                profile(),
                                widget_helper_));

比較重要的是建立IPC對象,首先是初始化一個ChannelID,ChannelID標識了一個屬於本RenerProcessHost的唯一的具名管道名,接著用這個ID建立一個IPC對象:

  channel_.reset(
      new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this,
                           resource_message_filter,
                           io_thread->message_loop(), true,
                           g_browser_process->shutdown_event()));

接著到了比較重要的地方,會對當前的運行模式做一個判斷,如果是單進程模式,不會建立進程,而是在主進程中建立一個RendererMainThread線程,如果是非按進程模式,會接著建立一個新的RenderProcess。調用的函數是:

  static bool run_renderer_in_process() {
    return run_renderer_in_process_;
  }

這是BrowserRenderProcessHost的父類的靜態成員函數,run_renderer_in_process_也是一個靜態變數,回顧一下主進程的初始化過程,ChromeMain的第三個參數TCHAR* command_line代表的就是啟動chrome.exe的時候傳遞進來的參數,前面一章已經介紹過,如果command_line是--single-process,那麼將運行在單進程模式下,那麼,會調用下面的代碼設定run_renderer_in_process_的值:

  if (single_process)
    RenderProcessHost::set_run_renderer_in_process(true);

再回到剛才的代碼,如果是單進程模型:

    in_process_renderer_.reset(new RendererMainThread(channel_id));

    base::Thread::Options options;
#if !defined(TOOLKIT_USES_GTK)
    // In-process plugins require this to be a UI message loop.
    options.message_loop_type = MessageLoop::TYPE_UI;
#else
    // We can't have multiple UI loops on GTK, so we don't support
    // in-process plugins.
    options.message_loop_type = MessageLoop::TYPE_DEFAULT;
#endif
    in_process_renderer_->StartWithOptions(options);

    OnProcessLaunched();  // Fake a callback that the process is ready.

首先建立RendererMainThread的對象,接著設定線程的類型為TYPE_UI,也就是說,這個線程是一個能接收處理windows系統訊息的線程,這與多進程模型是完全不同的。

最後調用n_process_renderer_->StartWithOptions(options);啟動這個線程的訊息迴圈。

如果是標準的多進程模型:

    CommandLine* cmd_line = new CommandLine(renderer_path);
    if (!renderer_prefix.empty())
      cmd_line->PrependWrapper(renderer_prefix);
    AppendRendererCommandLine(cmd_line);
    cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);

    // Spawn the child process asynchronously to avoid blocking the UI thread.
    // As long as there's no renderer prefix, we can use the zygote process
    // at this stage.
    child_process_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
        FilePath(),
#elif defined(POSIX)
        renderer_prefix.empty(),
        base::environment_vector(),
        channel_->GetClientFileDescriptor(),
#endif
        cmd_line,
        this));

    fast_shutdown_started_ = false;

上面做的主要工作就是建立一個新的RenderProcess,並且通過cmd_line把ChannelID傳遞給這個新的進程,這樣RenderProcess和RenerProcessHost才能建立一對一的關係,完成正常的處理序間通訊的任務。

接著再看看建立進程的具體實現,代碼位於:

src\chrome\browser\child_process_launcher.cc

代碼如下:

ChildProcessLauncher::ChildProcessLauncher(
#if defined(OS_WIN)
    const FilePath& exposed_dir,
#elif defined(OS_POSIX)
    bool use_zygote,
    const base::environment_vector& environ,
    int ipcfd,
#endif
    CommandLine* cmd_line,
    Client* client) {
  context_ = new Context();
  context_->Launch(
#if defined(OS_WIN)
      exposed_dir,
#elif defined(OS_POSIX)
      use_zygote,
      environ,
      ipcfd,
#endif
      cmd_line,
      client);
}

重點是context_->Launch,context_->Launch的唯一工作就是向BrowserThread線程發起一個Task,執行LaunchInternal函數,該函數調用handle = sandbox::StartProcessWithAccess(cmd_line, exposed_dir);

StartProcessWithAccess先通過傳遞的cmd_line確定進程的類型,枚舉類型定義在ChildProcessInfo類裡面,如下:

  enum ProcessType {
    UNKNOWN_PROCESS = 1,
    BROWSER_PROCESS,
    RENDER_PROCESS,
    PLUGIN_PROCESS,
    WORKER_PROCESS,
    NACL_LOADER_PROCESS,
    UTILITY_PROCESS,
    PROFILE_IMPORT_PROCESS,
    ZYGOTE_PROCESS,
    SANDBOX_HELPER_PROCESS,
    NACL_BROKER_PROCESS,
    GPU_PROCESS
  };

經過一系列判斷,如果非sandbox進程,那麼調用: base::LaunchApp(*cmd_line, false, false, &process);

如果是sandbox進程,調用  result = g_broker_services->SpawnTarget(
      cmd_line->GetProgram().value().c_str(),
      cmd_line->command_line_string().c_str(),
      policy, &target);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.