參考文章:
1.進程和線程
進程就像是一個有邊界的生產廠間,而線程就像是廠間內的一個個員工,可以自己做自己的事情,也可以相互配合做同一件事情。
當我們啟動一個應用,計算機會創建一個進程,操作系統會為進程分配一部分內存,應用的所有狀態都會保存在這塊內存中,應用也許還會創建多個線程來輔助工作,這些線程可以共享這部分內存中的數據。如果應用關閉,進程會被終結,操作系統會釋放相關內存。
一個進程還可以要求操作系統生成另一個進程來執行不同的任務,系統會為新的進程分配獨立的內存,兩個進程之間可以使用 IPC (Inter )進行通信。很多應用都會采用這樣的設計,如果一個工作進程反應遲鈍,重啟這個進程不會影響應用其它進程的工作。
關于進程和線程可以參考:
2.瀏覽器的架構
其實如果要開發一個瀏覽器,它可以是單進程多線程的應用,也可以是使用 IPC 通信的多進程應用。
不同瀏覽器的架構模型:
本文以 為例進行說明 :
采用多進程架構,其頂層存在一個 用以協調瀏覽器的其它進程。
具體來說,地主要進程及職責如下:
GPU
還為我們提供了「任務管理器」,供我們方便的查看當前瀏覽器中運行的所有進程及每個進程占用的系統資源,右鍵單擊還可以查看更多類別信息。
3.多進程架構的優缺點
優點:
1.某一渲染進程出問題不會影響其他進程
2.更為安全,在系統層面上限定了不同進程的權限
缺點:
由于不同進程間的內存不共享,不同進程的內存常常需要包含相同的內容。
為了節省內存,限制了最多的進程數瀏覽器工作原理是怎樣的,最大進程數量由設備的內存和 CPU 能力決定,當達到這一限制時,新打開的 Tab 會共用之前同一個站點的渲染進程。
把瀏覽器不同程序的功能看做服務,這些服務可以方便的分割為不同的進程或者合并為一個進程。以 為例,如果 運行在強大的硬件上,它會分割不同的服務到不同的進程,這樣 整體的運行會更加穩定,但是如果 運行在資源貧瘠的設備上,這些服務又會合并到同一個進程中運行,這樣可以節省內存。
的渲染——Site
在上面的進程圖中我們還可以看到一些進程下還存在著 ,這就是 Site 機制作用的結果。
Site 機制從 67 開始默認啟用。這種機制允許在同一個 Tab 下的跨站 使用單獨的進程來渲染,這樣會更為安全。
Site 被大家看做里程碑式的功能, 其成功實現是多年工程努力的結果。Site 不是簡單的疊加多個進程。這種機制在底層改變了 之間通信的方法, 的其它功能都需要做對應的調整,比如說 需要相應的支持,甚至 Ctrl + F 也需要支持。
關于 Site 的更多內容可參考下述鏈接:
4.導航過程發生了什么
也許大多數人使用 最多的場景就是在地址欄輸入關鍵字進行搜索或者輸入地址導航到某個網站,我們來看看瀏覽器是怎么看待這個過程的。
我們知道瀏覽器 Tab 外的工作主要由 掌控, 又對這些工作進一步劃分,使用不同線程進行處理:
瀏覽器主進程中不同的線程:
回到我們的問題,當我們在瀏覽器地址欄中輸入文字,并點擊回車獲得頁面內容的過程在瀏覽器看來可以分為以下幾步:
1.處理輸入
UI 需要判斷用戶輸入的是 URL 還是 query;
2.開始導航
當用戶點擊回車鍵,UI 通知 獲取網頁內容,并控制 tab 上的 展現,表示正在加載中。
會執行 DNS 查詢,隨后為請求建立 TLS 連接。
UI 通知 加載相關信息:
如果 接收到了重定向請求頭如 301, 會通知 UI 服務器要求重定向,之后,另外一個 URL 請求會被觸發。
3.讀取響應
當請求響應返回的時候瀏覽器工作原理是怎樣的, 會依據 -Type 及 MIME Type 判斷響應內容的格式。
如果響應內容的格式是 HTML ,下一步將會把這些數據傳遞給 ,如果是 zip 文件或者其它文件,會把相關數據傳輸給下載管理器。
Safe 檢查也會在此時觸發,如果域名或者請求內容匹配到已知的惡意站點, 會展示一個警告頁。此外 CORB 檢測也會觸發確保敏感數據不會被傳遞給渲染進程。
Safe :
CORB:+////.md
4.查找渲染進程
當上述所有檢查完成, 確信瀏覽器可以導航到請求網頁, 會通知 UI 數據已經準備好,UI 會查找到一個 進行網頁的渲染。
收到 返回的數據后,UI 查找相關的渲染進程:
由于網絡請求獲取響應需要時間,這里其實還存在著一個加速方案。當 UI 發送 URL 請求給 時,瀏覽器其實已經知道了將要導航到那個站點。UI 會并行的預先查找和啟動一個渲染進程,如果一切正常,當 接收到數據時,渲染進程已經準備就緒了,但是如果遇到重定向,準備好的渲染進程也許就不可用了,這時候就需要重啟一個新的渲染進程。
5.確認導航
進過了上述過程,數據以及渲染進程都可用了, 會給 發送 IPC 消息來確認導航,一旦 收到 的渲染確認消息,導航過程結束,頁面加載過程開始。
此時,地址欄會更新,展示出新頁面的網頁信息。 tab 會更新,可通過返回鍵返回導航來的頁面,為了讓關閉 tab 或者窗口后便于恢復,這些信息會存放在硬盤中。
和 通過 IPC 通信,請求 渲染頁面:
6.額外的步驟
一旦導航被確認, 會使用相關的資源渲染頁面,下文中我們將重點介紹渲染流程。當 渲染結束(渲染結束意味著該頁面內的所有的頁面,包括所有 都觸發了 時),會發送 IPC 信號到 , UI 會停止展示 tab 中的 。
發送 IPC 消息通知 頁面已經加載完成:
當然上面的流程只是網頁首幀渲染完成,在此之后,客戶端依舊可下載額外的資源渲染出新的視圖。
在這里我們可以明確一點,所有的 JS 代碼其實都由 控制的,所以在你瀏覽網頁內容的過程大部分時候不會涉及到其它的進程。不過也許你也曾經監聽過 事件,這個事件再次涉及到 和 的交互,當當前頁面關閉時(關閉 Tab ,刷新等等), 需要通知 進行相關的檢查,對相關事件進行處理。
瀏覽器進程發送 IPC 消息給渲染進程,通知要離開當前網站了:
如果導航由 觸發(比如在用戶點擊某鏈接,或者JS執行 . = "" ) 會首先檢查是否有 事件處理器,導航請求由 傳遞給
如果導航到新的網站,會啟用一個新的 來處理新頁面的渲染,老的進程會留下來處理類似 等事件。
關于頁面的生命周期,更多內容可參考:
瀏覽器進程發送 IPC 消息到新的渲染進程通知渲染新的頁面,同時通知舊的渲染進程卸載:
除了上述流程,有些頁面還擁有 (服務工作線程), 讓開發者對本地緩存及判斷何時從網絡上獲取信息有了更多的控制權,如果 被設置為從本地 cache 中加載數據,那么就沒有必要從網上獲取更多數據了。
值得注意的是 也是運行在渲染進程中的 JS 代碼,因此對于擁有 的頁面,上述流程有些許的不同。
當有 被注冊時,其作用域會被保存,當有導航時, 會在注冊過的 的作用域中檢查相關域名,如果存在對應的 ,UI 會找到一個 來處理相關代碼, 可能會從 cache 中加載數據,從而終止對網絡的請求,也可能從網上請求新的數據。
依據具體情形做處理:
關于 的更多內容可參考:
如果 最終決定通過網上獲取數據, 進程 和 進程的交互其實會延后數據的請求時間 。 是一種與 并行的加速加載資源的機制,服務端通過請求頭可以識別這類請求,而做出相應的處理。
更多內容可參考:
5.渲染進程是如何工作的
渲染進程幾乎負責 Tab 內的所有事情,渲染進程的核心目的在于轉換 HTML CSS JS 為用戶可交互的 web 頁面。渲染進程中主要包含以下線程:
1.主線程 Main
2.工作線程
3.排版線程
4.光柵線程
后文我們將逐步介紹不同線程的職責,在此之前我們先看看渲染的流程:
1.構建DOM
當渲染進程接收到導航的確認信息,開始接受 HTML 數據時,主線程會解析文本字符串為 DOM。
渲染 html 為 DOM 的方法由HTML 定義。
HTML :
2.加載次級的資源
網頁中常常包含諸如圖片,CSS,JS 等額外的資源,這些資源需要從網絡上或者 cache 中獲取。主進程可以在構建 DOM 的過程中會逐一請求它們,為了加速 會同時運行,如果在 html 中存在
等標簽, 會把這些請求傳遞給 中的 進行相關資源的下載。
3.JS的下載與執行
當遇到