瀏覽器進程之間協做的理解與研究

上篇文章咱們簡單的理解了瀏覽器的相關進程,以及各類進程模式,那麼這篇文章咱們就探究進程之間的協做吧,可能內容有些多,我能夠拆碎一些,可是這不是水文章哦~
單進程chrome

附:歷史文章

進程之間的協做

當打開瀏覽器,從輸入url到展現頁面,發生了什麼

這個實際上是一個老生常談的問題,聽說咱們CTO之前就很喜歡問這個...既然這樣那咱們再來從新梳理一下。瀏覽器

打開瀏覽器

說實話,這個地方的資料真的有些難找,只能逼着我找源碼了,簡單的說一下吧,否則我怎麼裝....要是有大神,請指教~,這裏代碼太多,沒興趣的同窗能夠直接看總結。markdown

Chrome的啓動文件

chrome_exe_main.cc這個文件是Chrome的啓動文件,一個是加載chrome.dll內核文件,檢查版本更新,初始化崩潰上報網絡

const wchar_t* dll_name = L"chrome.dll";
#if defined(GOOGLE_CHROME_BUILD)
  google_update::GoogleUpdateClient client;
  client.Init(L"{8A69D345-D564-463c-AFF1-A69D9E530F96}", dll_name);
  InitCrashReporter(client.GetDLLPath());
複製代碼

chrome_dll_main.cc在這個文件是能夠看到chrome.dll的入口函數是ChromeMain函數

DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance, sandbox::SandboxInterfaceInfo* sandbox_info, TCHAR* command_line, int show_command) 複製代碼

在這個文件中我發現了一些對進程的處理oop

extern int BrowserMain(CommandLine &, int, sandbox::BrokerServices*);
extern int RendererMain(CommandLine &, int, sandbox::TargetServices*);
extern int PluginMain(CommandLine &, int, sandbox::TargetServices*);
...
if (single_process)
 RenderProcessHost::set_run_renderer_in_process(true);
...
...
if (process_type.empty()) {
 file_state = logging::DELETE_OLD_LOG_FILE;
}

int rv;
if (process_type == switches::kRendererProcess) {
 rv = RendererMain(parsed_command_line, show_command, target_services);
} else if (process_type == switches::kPluginProcess) {
 rv = PluginMain(parsed_command_line, show_command, target_services);
} else if (process_type.empty()) {
 int ole_result = OleInitialize(NULL);
 DCHECK(ole_result == S_OK);
 rv = BrowserMain(parsed_command_line, show_command, broker_services);
 OleUninitialize();
} else {
 NOTREACHED() << "Unknown process type";
 rv = -1;
}
if (!process_type.empty()) {
 ResourceBundle::CleanupSharedInstance();
複製代碼
總結

綜上,咱們不難看出,ChromeMain一開始作了一些初始化的操做,不一樣類型的進程啓動入口都經過ChromeMain來統一處理。其中主要是browser、render還有plugin的進程。post

從輸入url到展現頁面,發生了什麼

我感受這個問題可能會很常見,那咱們就經過一個用戶正常打開瀏覽器以後的操做來進行分析吧。渲染進程除外,通熟的說是除了tab以外,有不少交互操做用是瀏覽器的主進程(Browser process)來處理,咱們比較常見的有:學習

  • UI thread : 控制瀏覽器上的按鈕及輸入框;
  • network thread: 處理網絡請求,從網上獲取數據;
  • storage thread: 控制文件等的訪問;

多進程
當咱們在地址欄中輸入一個地址以後,首先起做用的是UI線程(UI thread)。咱們輸入的地址千奇百怪,但正常的來講絕大部分確實也是URL,但這個是須要UI thread進行判斷的。ui

解析URL

首先他會分析這個URI是什麼,若是是http相關會進行DNS查詢等,而後直接調用http相關的模塊。但也有多是一個搜索地址。this

Browser* StartupBrowserCreatorImpl::OpenTabsInBrowser(Browser* browser, bool process_startup, const StartupTabs& tabs) {
  DCHECK(!tabs.empty());

  if (!profile_ && browser)
    profile_ = browser->profile();

  bool first_tab = true;
  ProtocolHandlerRegistry* registry = profile_ ?
      ProtocolHandlerRegistryFactory::GetForBrowserContext(profile_) : NULL;
  for (size_t i = 0; i < tabs.size(); ++i) {
    // We skip URLs that we'd have to launch an external protocol handler for.
    // This avoids us getting into an infinite loop asking ourselves to open
    // a URL, should the handler be (incorrectly) configured to be us. Anyone
    // asking us to open such a URL should really ask the handler directly.
    bool handled_by_chrome = ProfileIOData::IsHandledURL(tabs[i].url) ||
        (registry && registry->IsHandledProtocol(tabs[i].url.scheme()));
    if (!process_startup && !handled_by_chrome)
      continue;

    int add_types = first_tab ? TabStripModel::ADD_ACTIVE :
                                TabStripModel::ADD_NONE;
    add_types |= TabStripModel::ADD_FORCE_INDEX;
    if (tabs[i].is_pinned)
      add_types |= TabStripModel::ADD_PINNED;

    NavigateParams params(browser, tabs[i].url, ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
    params.disposition = first_tab ? WindowOpenDisposition::NEW_FOREGROUND_TAB
                                   : WindowOpenDisposition::NEW_BACKGROUND_TAB;
    params.tabstrip_add_types = add_types;

#if BUILDFLAG(ENABLE_RLZ)
    if (process_startup && google_util::IsGoogleHomePageUrl(tabs[i].url)) {
      params.extra_headers = rlz::RLZTracker::GetAccessPointHttpHeader(
          rlz::RLZTracker::ChromeHomePage());
    }
#endif // BUILDFLAG(ENABLE_RLZ)

    Navigate(&params);

    first_tab = false;
  }
  if (!browser->tab_strip_model()->GetActiveWebContents()) {
    // TODO(sky): this is a work around for 110909. Figure out why it's needed.
    if (!browser->tab_strip_model()->count())
      chrome::AddTabAt(browser, GURL(), -1, true);
    else
      browser->tab_strip_model()->ActivateTabAt(0);
  }

  browser->window()->Show();

  return browser;
}
複製代碼

綜合上邊的理解,實際上的流程以下:
多進程

下一篇文章咱們就詳細的來講說,瀏覽器從發出請求到收到請求以及處理的流程~

相關文章
相關標籤/搜索