最近看了很多关于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应用的朋友一些帮助。
由于个人水平有限,文中难免会有错误,也希望大家能提出意见和建议!