現代瀏覽器工做原理(一)——瀏覽器進程

1、序言

其實作了兩年前端,一直都是從代碼和網絡方面考量問題,一直都沒有考慮過跟用戶打交道最近的實際上是瀏覽器。瀏覽器這個東西怎麼說呢,從刀耕火種時代的ie瀏覽器,到表明現代先進的chrome瀏覽器,瀏覽器的整個架構發生了翻天覆地的變化。本章我就來說一下瀏覽器內核進程和架構的變化。 前端

2、進程、線程的概念

在講以前,先來看一下會提到的兩個概念,進程和線程。咱們知道,ie瀏覽器實際上是單進程的瀏覽器。而現代瀏覽器如谷歌瀏覽器爲例,它是多進程的瀏覽器。那對比單進程,現代瀏覽器的多進程有啥優點呢,在講這個問題以前,咱們先來了解一下進程和線程的概念。chrome

首先進程是一個程序的運行實例,咱們寫的代碼最後運行其實就是一個進程在運行,因此進程也能夠說是程序基本運行的單位。進程也有分主進程、父進程和子進程。主進程是進程的入口,若是你寫過Java的話,就會了解到Java里程序執行有一個main方法,這個main方法是程序的入口。通常來講,若是寫的進程夠簡單的話,主進程就是父進程。父子進程的關係其實就子進程獲得的是除了代碼段是與父進程共享的意外,其餘全部的都是獲得父進程的一個副本,子進程的全部資源都繼承父進程,獲得父進程資源的副本,既然爲副本,也就是說,兩者並不共享地址空間。,兩個是單獨的進程,繼承了之後兩者就沒有什麼關聯了,子進程單獨運行。數據庫

線程是獨立調度和分派的基本單位,也是操做系統可以進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運做單位。一條線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。在進程中,若是有多個線程處理一個代碼塊,咱們能夠稱之爲並行處理。好比下面這個代碼塊在單線程中則是要執行四步,而在多線程中前三行經過三個線程來執行,最後一行代碼則在最後的線程中執行展現便可:瀏覽器

var a = 1 + 1
var b = 2 * 2
var c = 3 / 3
console.log(a, b, c)複製代碼

總的來講,進程和線程之間的關係是這樣的:安全

  1. 在進程裏任意一個線程出錯都會致使整個進程崩潰。
  2. 進程裏的線程能夠共享進程裏的數據。
  3. 當一個進程關閉後,系統會回收進程所佔用的資源。
  4. 進程與進程之間的內容相互隔離,若是要實現進程與進程之間的通訊,則用IPC技術。

3、瀏覽器的單進程時代

在前端處於刀耕火種的年代,微軟經過在它的電腦設備上綁定了ie瀏覽器,逐漸的戰勝了昔日強敵網景,獨霸整個pc時代。以ie6爲例,這款瀏覽器就是典型的單進程瀏覽器,並且仍是單線程瀏覽器。因此你能夠想象,這個瀏覽器是奇慢無比,一個網頁掛了就會致使瀏覽器裏全部的頁面都掛了。因而乎在後面的ie瀏覽器,經過多線程技術來試圖提高瀏覽器的速度,但其實單進程不管怎麼魔改,都會涉及到這些問題:bash

  1. 不穩定。畢竟只要一個線程掛了就整個瀏覽器掛了,因此整個瀏覽器很不穩定。
  2. 不流暢。好比在經過網絡獲取資源,到渲染流程,若是瀏覽器上還有插件則還要考慮插件的運行,若是有一個腳本是死循環的,則致使全部頁面都要等待這個腳本執行完畢,會致使整個頁面十分的不流暢。而且單進程瀏覽器關閉一個頁面也會存在內存泄漏的問題,畢竟不是多進程。多進程關掉一個頁面至關於關掉一個進程,系統會自動回收資源。因此這樣子會致使瀏覽器開的越久就越佔用內存。
  3. 不安全。上面說到線程是能夠共享進程裏的資源的,若是一個插件是惡意的,它能夠影響到整個瀏覽器,甚至能夠控制你的電腦,來盜取帳號密碼。除了插件外,還有一些腳本能夠經過鑽漏洞來獲取權限,引起不少嚴重的後果。

4、瀏覽器的多進程時代

既然單進程時代的瀏覽器是有這麼多的漏洞,那麼多進程時代的瀏覽器是怎麼樣的呢?現代瀏覽器以chrome瀏覽器爲例,目前的瀏覽器的多進程架構大體上是這樣的:markdown

  1. 瀏覽器進程。該進程主要是負責界面顯示、用戶交互、子進程管理,同時提供存儲等功能。
  2. 網絡進程。該進程主要負責頁面的網絡資源加載,好比在地址欄輸入一個網頁地址,網絡進程會將請求後獲得的資源交給渲染進程處理。
  3. 渲染進程。核心任務是將 HTML、CSS 和 JavaScript 轉換爲用戶能夠與之交互的網頁,排版引擎 Blink 和 JavaScript 引擎 V8 都是運行在該進程中,默認狀況下,Chrome 會爲每一個 Tab 標籤建立一個渲染進程。出於安全考慮,渲染進程都是運行在沙箱模式下。
  4. GPU進程。其實,Chrome 剛開始發佈的時候是沒有 GPU 進程的。而 GPU 的使用初衷是爲了實現 3D CSS 的效果,只是隨後網頁、Chrome 的 UI 界面都選擇採用 GPU 來繪製,這使得 GPU 成爲瀏覽器廣泛的需求。最後,Chrome 在其多進程架構上也引入了 GPU 進程。
  5. 插件進程。主要是負責插件的運行,因插件易崩潰,因此須要經過插件進程來隔離,以保證插件進程崩潰不會對瀏覽器和頁面形成影響。

正是經過多進程,很好的解決了上面所提到的三個問題。首先chrome裏新開一個頁面至關於新開一個渲染進程,該頁面是不會影響到別的頁面執行。網絡

而後不流暢的問題,因爲經過多進程,JavaScript的腳本只有在渲染進程纔會被執行,因此若是出現死循環的問題也只是影響當前的頁面。而內存泄漏的問題也更容易解決,由於關閉了進程系統就會自動回收資源。多線程

最後就是安全問題。採用多進程架構的額外好處是可使用安全沙箱,你能夠把沙箱當作是操做系統給進程上了一把鎖,沙箱裏面的程序能夠運行,可是不能在你的硬盤上寫入任何數據,也不能在敏感位置讀取任何數據,例如你的文檔和桌面。Chrome 把插件進程和渲染進程鎖在沙箱裏面,這樣即便在渲染進程或者插件進程裏面執行了惡意程序,惡意程序也沒法突破沙箱去獲取系統權限。架構

不過筆者也有時偶然發如今chrome中,一個頁面的崩潰也會致使全部頁面的崩潰。緣由是這樣的,一般狀況下是一個頁面使用一個進程,可是,有一種狀況,叫"同一站點(same-site)",具體地講,咱們將「同一站點」定義爲根域名,還包含了該根域名下的全部子域名和不一樣的端口。Chrome的默認策略是,每一個標籤對應一個渲染進程。可是若是從一個頁面打開了新頁面,而新頁面和當前頁面屬於同一站點時,那麼新頁面會複用父頁面的渲染進程。官方把這個默認策略叫process-per-site-instance。直白的講,就是若是幾個頁面符合同一站點,那麼他們將被分配到一個渲染進程裏面去。因此,這種狀況下,一個頁面崩潰了,會致使同一站點的頁面同時崩潰,由於他們使用了同一個渲染進程。

爲何要讓他們跑在一個進程裏面呢?由於在一個渲染進程裏面,他們就會共享JS的執行環境,也就是說A頁面能夠直接在B頁面中執行腳本。由於是同一家的站點,因此是有這個需求的。

不過多進程瀏覽器也有它的缺點,第一就是更高的資源佔用。瀏覽器至關於父進程,瀏覽器下面的進程至關於子進程。由於每一個進程都會包含公共基礎結構的副本(如 JavaScript 運行環境),這就意味着瀏覽器會消耗更多的內存資源。

第二就是更復雜的架構體系。瀏覽器各模塊之間耦合性高、擴展性差等問題,會致使如今的架構已經很難適應新的需求了。

5、面向服務的架構

爲了解決這些問題,在 2016 年,Chrome 官方團隊使用「面向服務的架構」(Services Oriented Architecture,簡稱SOA)的思想設計了新的 Chrome 架構。也就是說 Chrome 總體架構會朝向現代操做系統所採用的「面向服務的架構」 方向發展,原來的各類模塊會被重構成獨立的服務(Service),每一個服務(Service)均可以在獨立的進程中運行,訪問服務(Service)必須使用定義好的接口,經過 IPC 來通訊,從而構建一個更內聚、鬆耦合、易於維護和擴展的系統,更好實現 Chrome 簡單、穩定、高速、安全的目標。

Chrome 最終要把 UI、數據庫、文件、設備、網絡等模塊重構爲基礎服務,相似操做系統底層服務。目前 Chrome 正處在老的架構向服務化架構過渡階段,這將是一個漫長的迭代過程。Chrome 正在逐步構建 Chrome 基礎服務(Chrome Foundation Service),若是你認爲 Chrome 是「便攜式操做系統」,那麼 Chrome 基礎服務即可以被視爲該操做系統的「基礎」系統服務層。同時 Chrome 還提供靈活的彈性架構,在強大性能設備上會以多進程的方式運行基礎服務,可是若是在資源受限的設備上,Chrome 會將不少服務整合到一個進程中,從而節省內存佔用。 

相關文章
相關標籤/搜索