CEF3是一個多進程架構框架,如果有了解過chromium的進程架構的,那么就很容易了解CEF3的多進程了。打開CEF3源代碼中發布的cefclient實例,如果打開的頁面帶有flash或者其他插件。在任務管理其中可以看到四個進程,顯示出命令行列。可以看到一個主進程,一般主進程是Browser進程,其他的分別是渲染進程(Render),GPU加速進程(GPU),插件進程(NPAPI或者PPAPI)。
Browser進程:被定義為主進程,負責窗口管理,界面繪制和網絡交互。
Render 進程:Blink的渲染和Js的執行被放在一個獨立的Render 進程中;除此之外,Render進程還負責Js Binding和對Dom節點的訪問。 默認的進程模型中,會為每個標簽頁創建一個新的Render進程。
NPAPI插件進程:按需創建,每種類型的插件只會有一個進程,每個插件進程可以被多個Render進程共享;
Pepper插件進程:同NPAPI插件進程,不同的是為Pepper插件而創建的進程;
GPU進程:按需創建,最多只有一個,當且僅當GPU硬件加速打開的時候才會被創建,主要用於對3D加速調用的實現。
多進程的好處很多,在瀏覽器中最主要的好處是當一個頁面或者插件崩潰或假死,不會給其他頁面帶來影響。CEF3的進程之間可以通過IPC進行通信。Browser和Render進程可以通過發送異步消息進行雙向通信。甚至在Render進程可以注冊在Browser進程響應的異步JavaScript API。在CEF3中,Browser和Render進程間可以通過SendProcessMessage(CefProcessId target_process, CefRefPtr<CefProcessMessage> message)函數實現消息傳遞。
默認情況下,主應用程序會被多次啟動運行各自獨立的進程。通過傳遞不同的命令行參數給CefExecuteProcess函數實現的。如果主應用程序很大,加載時間比較長,或者不能在非瀏覽器進程里使用,則宿主程序可使用獨立的可執行文件去運行這些進程。這可以通過配置 CefSettings.browser_subprocess_path變量做到。更
chromium本身支持多種進程模型,但CEF3主要是模型是兩種:單進程和為每個標簽創建一個進程。后一種是缺省行為,前邊一種可設置。通過設置命令行的--single-process,CEF3就可以支持用於調試目的的單進程運行模型。支持的平台為:Windows,Mac OS X 和Linux。
一圖解千語,下圖給出了缺省的chromium瀏覽器的進程模型。方框代表進程,連接線代表IPC進程間通信。

由於關於cef3進程架構的講解很少,個人猜測CEF3的進程架構和chromium應該差不多,畢竟CEF3是基於chromium的框架。更多和進程相關的內容可以網上搜索“chromium多進程架構”。
在CEF3中,每個進程都會運行多個線程。完整的線程類型表請參照cef_thread_id_t
typedef enum {
// BROWSER PROCESS THREADS -- Only available in the browser process.
///
// The main thread in the browser. This will be the same as the main
// application thread if CefInitialize() is called with a
// CefSettings.multi_threaded_message_loop value of false.
///
TID_UI,
// Used to interact with the database.
TID_DB,
///
// Used to interact with the file system.
///
TID_FILE,
// Used for file system operations that block user interactions.
// Responsiveness of this thread affects users.
TID_FILE_USER_BLOCKING,
///
// Used to launch and terminate browser processes.
///
TID_PROCESS_LAUNCHER,
// Used to handle slow HTTP cache operations.
TID_CACHE,
// Used to process IPC and network messages.
TID_IO,
// RENDER PROCESS THREADS -- Only available in the render process.
///
// The main thread in the renderer. Used for all WebKit and V8 interaction.
///
TID_RENDERER,
} cef_thread_id_t;
在Browser進程中包含如下主要的線程:
- TID_UI 線程是瀏覽器的主線程。如果應用程序在調用調用CefInitialize()時,傳遞CefSettings.multi_threaded_message_loop=false,這個線程也是應用程序的主線程。
- TID_IO 線程主要負責處理IPC消息以及網絡通信。
- TID_FILE 線程負責與文件系統交互。
由於CEF采用多線程架構,有必要使用鎖和閉包來保證數據的線程安全語義。IMPLEMENT_LOCKING定義提供了Lock()和 Unlock()方法以及AutoLock對象來保證不同代碼塊同步訪問數據。CefPostTask函數組支持簡易的線程間異步消息傳遞。更多信息,請參考Posting Tasks章節。
可以通過CefCurrentlyOn()方法判斷當前所在的線程環境,cefclient工程使用下面的定義來確保方法在期望的線程中被執行。
#define REQUIRE_UI_THREAD() ASSERT(CefCurrentlyOn(TID_UI));
#define REQUIRE_IO_THREAD() ASSERT(CefCurrentlyOn(TID_IO));
#define REQUIRE_FILE_THREAD() ASSERT(CefCurrentlyOn(TID_FILE));
