最近看了很多關於Webkit原理的博客和資料,大都是介紹整體構架和諸如資源加載、HTML解析、Rendering等服務端進程的原理。
但是新版本的Webkit(Webkit2)是一個多進程模型,而不是過去的單進程模型。
這些進程分為兩類,分別是:服務端(WebProcess)和客戶端(UIProcess)
客戶端資料的缺少使得我對客戶端進程產生了興趣,經過對代碼的研究,找出了一點門道,這里分享給大家。
首先介紹一下兩個進程的關系
顧名思義,服務端就是完成客戶端發來的請求並回應,而客戶端就是資源或功能的請求者,只不過他們不像Web服務器和瀏覽器一樣處於不同的機器(一般都這樣),他們只是兩個進程而已。這樣做的好處是使得兩部分隔離,就算服務進程宕了也不影響客戶進程,可以重新啟動,反之亦然,同時多個客戶進程能夠共享同一個服務進程,減少了資源開銷。兩個進程間的通信是通過消息隊列實現的,客戶端發送消息到服務端的消息隊列,服務端在空閑時取出一條消息並處理,這樣的設計可以減少多進程同步的開銷。在Windows下他們是通過命名管道來收發消息的。
客戶端大部分功能的實現都采用了代理模式,即用戶不直接使用消息機制和服務端通信,而是通過客戶端的代理進行。我們如果看到代碼中有些類名以Proxy結尾,說明這個類就是個代理類,用戶通過調用他提供的方法就能實現功能,而在代理內部實現則是向服務端發出對應的消息而真正實現所需的功能。
下面介紹一個典型的調用過程:創建一個WebView
我們使用API WKViewCreate來創建一個WebView並得到它的引用WebViewRef
調用過程如下(縮進表示調用關系)
::WKViewCreate()
WebView::create()
{
//創建WebView依附的窗口
::CreateWindow()
//如果是ProcessContext那么就是創建雙進程模型,ThreadContext則是單進程
WebContext::createWebPage()
{
//確保當前服務端進程在運行
WebContext::ensureWebProcess()
{
WebProcessProxy::create()
WebProcessProxy::connect()
//如果當前沒有服務端進程就創建一個,否則直接建立連接
ProcessLauncher::create()
ProcessLauncher::launchProcess()
{
::CreateNamedPipe() //創建和服務端通信的管道
::CreateProcess() //創建Webkit2WebProcess進程
}
//服務端進程啟動之后的回調
ProcessLauncher::didFinishLaunchingProcess()
{
//建立連接發送消息
WebConnectionToWebProcess::create()
WebConnectionToWebProcess::open()
}
//和服務端連接建立后,發送初始化消息
WebProcessProxy::send(init message)
}
//通過代理發送消息創建一個WebView對象
WebProcessProxy::createWebPage()
WebPageProxy::create()
}
}
至此,我們就完成了服務端的創建過程並獲得了一個新的WebView引用
最后,希望這篇文章能給研究Webkit應用的朋友一些幫助。
由於個人水平有限,文中難免會有錯誤,也希望大家能提出意見和建議!