多進(jìn)程架構(gòu)(原文地址:http://www.chromium.org/developers/design-documents/multi-process-architecture)
成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括太和網(wǎng)站建設(shè)、太和網(wǎng)站制作、太和網(wǎng)頁(yè)制作以及太和網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,太和網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到太和省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!這篇文檔描述了Chromium的上層架構(gòu)。
a、問題所在
幾乎沒可能建立一個(gè)永遠(yuǎn)不崩潰或掛機(jī)的渲染引擎,也不可能建立一個(gè)完美安全的渲染引擎。
某些方面來說,現(xiàn)在的Browser有點(diǎn)像過去的單用戶,多任務(wù)的操作系統(tǒng)。在那樣的操作系統(tǒng)里,如果有一個(gè)胡作非為的程序,將會(huì)讓整個(gè)系統(tǒng)崩潰。也就像一個(gè)胡作非為的頁(yè)面、或插件錯(cuò)誤,就能帶來整個(gè)瀏覽器和當(dāng)前運(yùn)行的所有標(biāo)簽的崩潰。
現(xiàn)在的操作系統(tǒng)強(qiáng)壯多了,因?yàn)樗麄儗?yīng)用程序劃分到一個(gè)個(gè)的獨(dú)立進(jìn)程中,這些進(jìn)程間獨(dú)立運(yùn)行,不互相影響,一個(gè)程序中的crash一般不會(huì)影響到別的應(yīng)用程序或者整個(gè)系統(tǒng),而且某用戶要訪問別的用戶的數(shù)據(jù)也是不允許的。
b、架構(gòu)概覽
主進(jìn)程,也叫做"Browser"進(jìn)程,運(yùn)行UI和管理tab。
同樣的,tab進(jìn)程叫做"Render"進(jìn)程,使用web-kit排布引擎來解析和排布HTML。
c、管理多個(gè)Render進(jìn)程
每個(gè)Render進(jìn)程都有一個(gè)全局的RenderProcess對(duì)象管理和父進(jìn)程(Browser)間的通信以及全局的狀態(tài),Browser對(duì)每個(gè)RenderProcess都維護(hù)了一個(gè)對(duì)應(yīng)的RenderProcessHost,用來管理Browser的狀態(tài)和用于通信。Browser和Renderer之間的通訊使用Chromium\'sIPCsystem。
d、管理視圖
每個(gè)Render進(jìn)程都有一個(gè)或者多個(gè)的RenderView對(duì)象,這些對(duì)象都由RenderProcess管理,RenderView對(duì)應(yīng)著每個(gè)Tab的內(nèi)容。
對(duì)應(yīng)的RenderProcessHost維護(hù)著一個(gè)RenderViewHost對(duì)象,這個(gè)對(duì)象對(duì)應(yīng)著每個(gè)Renderer里的view。
每個(gè)view擁有一個(gè)viewID,這個(gè)viewID是用來區(qū)分一個(gè)renderer里的多個(gè)不同的view,并且這些id在一個(gè)renderer進(jìn)程中是唯一的,但在整個(gè)Browser中不是唯一的,所以要區(qū)分一個(gè)view需要一個(gè)RenderProcessHost和一個(gè)ViewID。
從Browser到指定的tab內(nèi)容之間的通信是通過這些RenderViewHost對(duì)象來完成的,這些RenderViewHost對(duì)象知道怎么把消息通過RenderProcessHost傳到RenderProcess,然后再傳到RenderView。
e、組件和接口
在Render進(jìn)程中:
RenderProcess處理IPC是通過Browser中對(duì)應(yīng)的RenderProcessHost,每個(gè)render進(jìn)程都只有一個(gè)RenderProcess,這就是browser和render的通信路徑了。
RenderView對(duì)象和Browser中對(duì)應(yīng)的RenderViewHost通信(通過RenderProcess),RenderView對(duì)象也和我們的WebKit嵌入層通信。這個(gè)對(duì)象代表tab或窗口里的頁(yè)面內(nèi)容。
在Browser進(jìn)程中:
Browser對(duì)象代表高層的瀏覽器窗口。
RenderProcessHost對(duì)象代表browser端,browser和renderView的通信,每個(gè)render進(jìn)程只有一個(gè)RenderProcessHost。
RenderViewHost對(duì)象包裝了和RenderView的通信。
browser中的RenderWidgetHost處理RenderWidget的輸入和繪畫。
f、共享render進(jìn)程
一般來說,一個(gè)新窗口或者一個(gè)新tab,就會(huì)創(chuàng)建一個(gè)新進(jìn)程,并創(chuàng)建一個(gè)RenderView,但有時(shí)候,可能要多個(gè)tab共享一個(gè)Render進(jìn)程。
一個(gè)web應(yīng)用打開一個(gè)新窗口的時(shí)候,他是期待一個(gè)同步的通信的,比如javascript的window.open,這個(gè)情況下,我們需要在新開的窗口中重用這個(gè)進(jìn)程。
我們也有辦法讓一個(gè)新的tab指向一個(gè)已存在的render進(jìn)程,這種情形是用于進(jìn)程太多的情況,或者用戶已經(jīng)有一個(gè)進(jìn)程打開導(dǎo)航到域名。這些辦法你可以查看這里(http://www.chromium.org/developers/design-documents/process-models)。
g、監(jiān)測(cè)崩潰和胡作非為的renderer
每個(gè)IPC連接到browser進(jìn)程,browser進(jìn)程都會(huì)監(jiān)測(cè)進(jìn)程的句柄。
如果這些句柄激發(fā),render進(jìn)程已經(jīng)崩潰并且tabs被告知這個(gè)崩潰。到現(xiàn)在為止,我們會(huì)顯示一個(gè)“sadtab”的頁(yè)面,通知用戶,這個(gè)renderer已經(jīng)崩潰了。點(diǎn)擊reload按鈕可以讓這個(gè)頁(yè)面重新裝載,或者打開一個(gè)新的導(dǎo)航。當(dāng)這個(gè)發(fā)生,我們會(huì)通知已經(jīng)沒有進(jìn)程,并會(huì)創(chuàng)建一個(gè)新的。
h、讓renderer變成一個(gè)沙箱
假設(shè)Webkit運(yùn)行在一個(gè)單獨(dú)的進(jìn)程中,我們可以限制它訪問系統(tǒng)資源。例如我們可以讓這個(gè)renderer只是通過他的父進(jìn)程browser訪問網(wǎng)絡(luò),同樣的,我們可以通過操作系統(tǒng)的權(quán)限系統(tǒng)來限制它訪問文件系統(tǒng)。
除了限制renderer訪問文件系統(tǒng)和網(wǎng)絡(luò),我們還可以限制它訪問用戶的顯示和相關(guān)的對(duì)象。我們每個(gè)render進(jìn)程都運(yùn)行在一個(gè)看不到的窗口里,這個(gè)窗口是獨(dú)立的,叫做“Desktop”,這可以阻止一個(gè)“危險(xiǎn)的”renderer(被植入危險(xiǎn)的代碼)打開一個(gè)新window或者截取你的鍵盤點(diǎn)擊。
i、把內(nèi)存還回去
正因?yàn)閞enderer運(yùn)行在一個(gè)單獨(dú)的進(jìn)程中,所以我們需要考慮隱藏的tabs的低優(yōu)先級(jí)問題。
正常的,windows會(huì)把一個(gè)最小化的進(jìn)程自動(dòng)放進(jìn)一個(gè)“有效的內(nèi)存池”中,當(dāng)這個(gè)進(jìn)程處于low-memory狀態(tài),windows將把這個(gè)內(nèi)存存放到硬盤中,直到他們變?yōu)閔igher-priority的內(nèi)存。
為了讓用戶可見的程序更良好的反應(yīng),我們可以把這個(gè)原則用于“隱藏”的tabs,當(dāng)一個(gè)renderer不是高級(jí)別的tab時(shí),我們可以釋放那個(gè)進(jìn)程的“workingset”大小,作為對(duì)系統(tǒng)的暗示,以便系統(tǒng)能把它的內(nèi)存轉(zhuǎn)放到硬盤上(如果系統(tǒng)認(rèn)為需要的話)。
因?yàn)槲覀儼l(fā)現(xiàn),減少workingset的大小,也會(huì)降低tab切換的性能。當(dāng)用戶在兩個(gè)tabs之間切換,我們漸漸的釋放內(nèi)存。這意味著,如果用戶切換回最近使用的標(biāo)簽,該標(biāo)簽的內(nèi)存是更可能被頁(yè)面化(存到disk)的,而少用的tab反而不會(huì)被頁(yè)面化。
當(dāng)然,有足夠內(nèi)存的用戶不用管這個(gè),因?yàn)閣indows只回收他需要的數(shù)據(jù),所以如果內(nèi)存足夠,這樣做對(duì)性能沒有一點(diǎn)的好處。
這有助于我們?cè)诘蛢?nèi)存的情況下得到更優(yōu)化的內(nèi)存占用,少用的tab將會(huì)被完全從內(nèi)存替換到硬盤,而前端的tab,將可以整個(gè)裝載進(jìn)來內(nèi)存中。相比之下,一個(gè)單進(jìn)程的瀏覽器將其所有的tab數(shù)據(jù)隨機(jī)的分發(fā)到內(nèi)存中,這樣就沒辦法把使用或者不實(shí)用的數(shù)據(jù)分離得那么清晰,這樣就浪費(fèi)內(nèi)存以及性能了。
j、插件
Firefox風(fēng)格的NPAPI插件會(huì)運(yùn)行在他自己的進(jìn)程中,和renderer隔開。具體可以看這里:http://www.chromium.org/developers/design-documents/plugin-architecture。