chrome多進程架構

問題

構建幾乎不會崩潰或掛起的渲染引擎幾乎是不可能的。構建完全安全的渲染引擎幾乎也是不可能的。

在某種程度上,2006年左右的網絡瀏覽器的狀態類似于過去的單用戶,協作多任務操作系統。由于此類操作系統中的行為異常的應用程序可能會破壞整個系統,因此Web瀏覽器中的行為異常的網頁也可能因此而崩潰。它只需要一個瀏覽器或插件錯誤即可關閉整個瀏覽器和所有當前運行的選項卡。

現代操作系統更強大,因為它們將應用程序置于相互隔離的單獨進程中。一個應用程序中的崩潰通常不會損害其他應用程序或操作系統的完整性,并且每個用戶對其他用戶數據的訪問受到限制。

建筑概述

我們對瀏覽器選項卡使用單獨的過程,以保護整個應用程序免受渲染引擎中的錯誤和干擾。我們還限制了每個渲染引擎進程對其他進程以及系統其余部分的訪問。在某些方面,這為Web瀏覽帶來了內存保護和訪問控制帶給操作系統的好處。

我們將運行UI并管理選項卡和插件過程的主要過程稱為“瀏覽器過程”或“瀏覽器”。同樣,特定于選項卡的過程稱為“渲染過程”或“渲染器”。渲染器使用Blink開源布局引擎來解釋和布局HTML。

管理渲染過程

每個渲染進程都有一個全局RenderProcess對象,該對象管理與父瀏覽器進程的通信并維護全局狀態。瀏覽器RenderProcessHost?為每個渲染進程維護一個對應項,該進程管理瀏覽器狀態和渲染器的通信。瀏覽器和渲染器使用Chromium的IPC系統進行通信。

管理視圖

每個渲染過程都有一個或多個RenderView對象,由管理RenderProcess,這些對象對應于內容的選項卡。對應項?在渲染器中RenderProcessHost維護RenderViewHost與每個視圖對應的內容。每個視圖都有一個視圖ID,該ID用于區分同一渲染器中的多個視圖。這些ID在一個渲染器中是唯一的,但在瀏覽器中不是唯一的,因此要識別視圖,需要一個RenderProcessHostID和一個View ID。通過這些RenderViewHost對象可以完成從瀏覽器到特定內容選項卡的通信,這些對象知道如何將消息通過它們發送RenderProcessHostRenderProcessRenderView。

組件和接口

在渲染過程中:

  • 在瀏覽器中RenderProcess使用相應的句柄處理IPC?RenderProcessHost。RenderProcess每個渲染過程只有一個對象。這就是所有瀏覽器↔渲染器通信的發生方式。
  • RenderView對象RenderViewHost在瀏覽器進程中(通過RenderProcess)和我們的WebKit嵌入層與其對應的對象通信。此對象表示選項卡或彈出窗口中一個網頁的內容

在瀏覽器過程中:

  • Browser對象表示頂級瀏覽器窗口。
  • RenderProcessHost對象表示單個瀏覽器↔渲染器IPC連接的瀏覽器端。有一個RenderProcessHost在每個渲染過程中的瀏覽器進程。
  • RenderViewHost對象封裝的通信與遠程RenderViewRenderWidgetHost處理用于輸入和繪畫RenderWidget在瀏覽器中。

有關此嵌入的工作方式的更多詳細信息,請參閱Chromium如何顯示網頁??設計文檔。

共享渲染過程

通常,每個新窗口或選項卡都會在新過程中打開。瀏覽器將產生一個新進程,并指示它創建一個RenderView。

有時有必要或希望在選項卡或窗口之間共享渲染過程。Web應用程序會打開一個新窗口,希望與之進行同步通信,例如,使用??JavaScript中的window.open。在這種情況下,當我們創建新的窗口或選項卡時,我們需要重用打開窗口的過程。如果進程總數太大,或者用戶已經打開一個導航到該域的進程,我們還可以為新進程分配新選項卡的策略。這些策略在過程模型中進行了描述。

檢測崩潰或行為異常的渲染器

與瀏覽器進程的每個IPC連接都會監視進程句柄。如果發出了這些句柄的信號,則表示渲染過程已崩潰,并且向選項卡通知了崩潰?,F在,我們顯示一個“悲傷的標簽”屏幕,通知用戶渲染器崩潰了??梢酝ㄟ^按下重新加載按鈕或開始新的導航來重新加載頁面。發生這種情況時,我們注意到沒有任何流程,而是創建一個新的流程。

沙盒渲染器

鑒于渲染器在單獨的進程中運行,我們有機會通過sandboxing限制其對系統資源的訪問。例如,我們可以確保渲染器對網絡的唯一訪問是通過其父瀏覽器進程進行的。同樣,我們可以使用主機操作系統的內置權限來限制其對文件系統的訪問。

除了限制渲染器對文件系統和網絡的訪問之外,我們還可以限制對渲染器對用戶的顯示和相關對象的訪問。我們在用戶看不見的單獨Windows“?桌面?”?上運行每個渲染過程。這樣可以防止受損的渲染器打開新窗口或捕獲擊鍵。

回饋記憶

給定渲染器在單獨的進程中運行,將隱藏的選項卡視為較低優先級就變得很簡單。通常,Windows上最小化的進程會將其內存自動放入“可用內存”池中。在低內存情況下,Windows將在交換出更高優先級的內存之前將該內存交換到磁盤上,從而有助于使用戶可見的程序具有更高的響應速度。我們可以將相同的原理應用于隱藏的標簽。當渲染進程沒有頂級選項卡時,我們可以釋放該進程的“工作集”大小,以提示系統在必要時先將該內存換出到磁盤。因為我們發現減小工作集大小也會降低用戶在兩個選項卡之間切換時的選項卡切換性能,所以我們逐漸釋放此內存。這意味著,如果用戶切換回最近使用的選項卡,則與最近使用的選項卡相比,該選項卡的內存更有可能被分頁。具有足夠內存來運行所有程序的用戶根本不會注意到此過程:Windows僅會在需要時才真正回收這些數據,因此,如果有足夠的內存,則不會對性能造成任何影響。

這有助于我們在低內存情況下獲得更好的內存占用。與很少使用的背景標簽相關聯的內存可以完全換出,而前景標簽的數據可以完全加載到內存中。相比之下,單進程瀏覽器會將所有選項卡的數據隨機分布在其內存中,并且不可能如此干凈地分離使用和未使用的數據,從而浪費內存和性能。

插件和擴展

Firefox風格的NPAPI插件在其自身的進程中運行,與渲染器分開。插件體系結構中對此進行了詳細描述。?

“?網站隔離”項目旨在提供渲染器之間的更多隔離,該項目的早期交付成果包括在隔離的進程中運行Chrome的HTML / JavaScript內容擴展。