Chrom 的多進程架構

多進程架構(原文地址:http://www.chromium.org/developers/design-documents/multi-process-architecture )javascript

這篇文檔描述了 Chromium 的上層架構。前端

a、問題所在java

幾乎沒可能創建一個永遠不崩潰或掛機的渲染引擎,也不可能創建一個完美安全的渲染引擎。web

某些方面來講,如今的 Browser 有點像過去的單用戶,多任務的操做系統。在那樣的操做系統裏,若是有一個胡做非爲的程序,將會讓整個系統崩潰。也就像一個胡做非爲的頁面、或插件錯誤,就能帶來整個瀏覽器和當前運行的全部標籤的崩潰。windows

如今的操做系統強壯多了,由於他們將應用程序劃分到一個個的獨立進程中,這些進程間獨立運行,不互相影響,一個程序中的crash通常不會影響到別的應用程序或者整個系統,並且某用戶要訪問別的用戶的數據也是不容許的。瀏覽器

b、架構概覽安全


主進程,也叫作 "Browser" 進程,運行UI 和管理tab網絡

一樣的,tab進程叫作 "Render" 進程,使用 web-kit 排布引擎來解析和排布 HTML架構

c、管理多個Render 進程性能

每一個Render 進程都有一個全局的 RenderProcess 對象管理和父進程(Browser)間的通訊以及全局的狀態,Browser對每一個RenderProcess都維護了一個對應的 RenderProcessHost,用來管理 Browser 的狀態和用於通訊。Browser 和 Renderer 之間的通信使用 Chromium's IPC system

d、管理視圖

每一個Render 進程都有一個或者多個的RenderView對象,這些對象都由RenderProcess管理,RenderView對應着每一個 Tab的內容。

對應的 RenderProcessHost 維護着一個 RenderViewHost 對象,這個對象對應着每一個 Renderer裏的view

每一個 view 擁有一個 viewID,這個viewID是用來區分一個renderer裏的多個不一樣的view,而且這些id在一個 renderer進程中是惟一的,但在整個Browser 中不是惟一的,因此要區分一個view須要一個RenderProcessHost和一個View ID

Browser到指定的tab內容之間的通訊是經過這些 RenderViewHost 對象來完成的,這些RenderViewHost對象知道怎麼把消息經過 RenderProcessHost 傳到 RenderProcess ,而後再傳到 RenderView

e、組件和接口

在 Render 進程中:

  • RenderProcess 處理 IPC 是經過Browser 中對應的 RenderProcessHost,每一個render 進程都只有一個RenderProcess,這就是browserrender的通訊路徑了。

  • RenderView 對象和 Browser 中對應的RenderViewHost通訊(經過 RenderProcess),RenderView 對象也和咱們的WebKit 嵌入層通訊。這個對象表明tab或窗口裏的頁面內容。

Browser 進程中:

  • Browser對象表明最高層的瀏覽器窗口。

  • RenderProcessHost對象表明browser 端,browserrenderView的通訊,每一個render 進程只有一個 RenderProcessHost

  • RenderViewHost 對象包裝了和 RenderView 的通訊。

  • browser中的RenderWidgetHost 處理RenderWidget的輸入和繪畫。

f、共享render進程

通常來講,一個新窗口或者一個新tab,就會建立一個新進程,並建立一個RenderView,但有時候,可能要多個tab共享一個Render進程。

一個web應用打開一個新窗口的時候,他是期待一個同步的通訊的,好比javascript的 window.open,這個狀況下,咱們須要在新開的窗口中重用這個進程。

咱們也有辦法讓一個新的tab指向一個已存在的render進程,這種情形是用於進程太多的狀況,或者用戶已經有一個進程打開導航到域名。這些辦法你能夠查看這裏(http://www.chromium.org/developers/design-documents/process-models )。

g、監測崩潰和胡做非爲的renderer

每一個IPC鏈接到browser進程, browser進程都會監測進程的句柄。

若是這些句柄激發,render進程已經崩潰而且tabs被告知這個崩潰。到如今爲止,咱們會顯示一個「sad tab」的頁面,通知用戶,這個renderer已經崩潰了。點擊reload按鈕可讓這個頁面從新裝載,或者打開一個新的導航。當這個發生,咱們會通知已經沒有進程,並會建立一個新的。

h、讓renderer變成一個沙箱

假設Webkit運行在一個單獨的進程中,咱們能夠限制它訪問系統資源。例如咱們可讓這個renderer只是經過他的父進程browser訪問網絡,一樣的,咱們能夠經過操做系統的權限系統來限制它訪問文件系統。

除了限制renderer訪問文件系統和網絡,咱們還能夠限制它訪問用戶的顯示和相關的對象。咱們每一個render進程都運行在一個看不到的窗口裏,這個窗口是獨立的,叫作「Desktop」,這能夠阻止一個「危險的」renderer(被植入危險的代碼)打開一個新window或者截取你的鍵盤點擊。

i、把內存還回去

正由於renderer運行在一個單獨的進程中,因此咱們須要考慮隱藏的tabs的低優先級問題。

正常的,windows會把一個最小化的進程自動放進一個「有效的內存池」中,當這個進程處於 low-memory 狀態,windows 將把這個內存存放到硬盤中,直到他們變爲higher-priority的內存。

爲了讓用戶可見的程序更良好的反應,咱們能夠把這個原則用於「隱藏」的tabs,當一個renderer不是最高級別的tab時,咱們能夠釋放那個進程的 「working set」大小,做爲對系統的暗示,以便系統能把它的內存轉放到硬盤上(若是系統認爲須要的話)。

由於咱們發現,減小working set 的大小,也會下降tab切換的性能。當用戶在兩個tabs之間切換,咱們漸漸的釋放內存。這意味着,若是用戶切換回最近使用的標籤,該標籤的內存是更可能被頁面化(存到disk)的,而少用的tab反而不會被頁面化。

固然,有足夠內存的用戶不用管這個,由於windows只回收他須要的數據,因此若是內存足夠,這樣作對性能沒有一點的好處。

這有助於咱們在低內存的狀況下獲得更優化的內存佔用,少用的tab將會被徹底從內存替換到硬盤,而前端的tab,將能夠整個裝載進來內存中。相比之下,一個單進程的瀏覽器將其全部的tab數據隨機的分發到內存中,這樣就沒辦法把使用或者不實用的數據分離得那麼清晰,這樣就浪費內存以及性能了。

j、插件

Firefox風格的 NPAPI 插件會運行在他本身的進程中,和renderer隔開。具體能夠看這裏:http://www.chromium.org/developers/design-documents/plugin-architecture 。

相關文章
相關標籤/搜索