微信公众号:爱写bugger的阿拉斯加
若有问题或建议,请后台留言,我会尽力解决你的问题。
此文章是我最近在看的【WebKit 技术内幕】一书的一些理解和作的笔记。
而【WebKit 技术内幕】是基于 WebKit 的 Chromium 项目的讲解。程序员
WebKit 的一个显著特征就是支持不一样的浏览器,由于不一样浏览器的需求不一样,因此在 WebKit 中一些代码 能够共享,可是另一部分是不一样的,这些不一样的部分称为 WebKit 的移植( Ports )。
上图的 WebKit 架构,虚线框表示该部分模块在不一样浏览器使用的 WebKit 内核中的实现是不一样的,也就是它们 不是广泛共享的。用实线框表示的部分,表示它们是基本上是共享的,但不是绝对,是由于它们中的一些特性可能并非共享的,并且能够经过不一样的编译设置改变它们的行为。web
图中最下面的是操做系统,不一样浏览器可能会依赖不一样的操做系统,同一个浏览器使用的 WebKit 也可能依赖不一样的的操做系统。数据库
操做系统之上的就是 WebKit 赖以工做的众多第三方库,这些库是 WebKit 运行的基础。编程
在它们两者之上的就是 WebKit 项目了。浏览器
WebCore 包含了了目前被 各个浏览器所使用的 WebKit 共享部分,这些都是加载和渲染网页的基础部分,它们必不可少,包括 HTML (解释器)、CSS (解释器)、SVG、DOM、渲染树(RenderObject 树和RenderLqyer 树等),以及 Inspector(Web Inspector和调试网页)。这些共享部分有些是基础框架,其背后支持也须要各个平台的不一样实现。安全
JavaScriptCore 引擎是 WebKit 中默认 JavaScript 引擎,也就是说一些 WebKit 的移植使用该引擎。并且它只是默认,并非惟一的,是能够替换的。事实上,WebKit 中对 JavaScript 引擎的调用是独立于引擎的。在 Google 的 Chormium 开源项目中,它被替换成 V8 引擎。微信
WebKit Ports 指的是 WebKit 中的非共享部分,对于不一样浏览器使用的 WebKit 来讲,移植中的这些模块因为平台差别、第三方库和需求不一样等缘由,每每按照本身的方式来设计与实现,这就产生了移植部分,这也是致使众多 WebKit 版本的行为并不是一到的重要缘由。这其中包括硬件的 加速架构,网络栈,视频解码,图片解码等。网络
在 WebCore 和 WebKit Ports 之上的层主要是提供嵌入式编程接口,这些接口是提供给浏览器调用(固然也能够有其余使用者)。图中有左右两个部分分别是狭义 WebKit 的接口和 WebKit2 的接口。由于接口与具体的移植有关,因此有一个与浏览器相关的绑定层。绑定层上面就是 WebKit 项目对外暴露的接口层。实际上接口层的定义也是与移植密切相关的,而不是 WebKit 有什么统一接口。多线程
WebKit 还有一个部分在图中没有展示出来,那就是测试用例,包括布局测试用例( Layout Tests )和性能测试用例( Performance Tests ),这两类测试包括了大量的测试用例和指望结果。为了保证 WebKit 的代码质量,这些用例被用来验证渲染结果的正确性。架构
Chromium 也是基于 WebKit ( Blink ) 的,并且在 WebKit 的移植部分中,因此能够经过 Chromium 能够了解如何基于 WebKit 构建浏览器。
在上面这些模块之上的就是著名 的 "Content 模块" 和 “Content API(接口)”,它们是 Chromium 对渲染网页功能的抽象。"Content 模块" 的本意是指网页的内容,这里是指用来渲染内容的模块。若是没有 Content 模块,浏览器的开发者也能够在 WebKit 的 Chormium 移植上渲染网页内容,可是没有办法得到沙箱模型。跨进程的 GPU 硬件加速机制、众多的 HTML5 功能,由于这些功能 不少是在 Content 层里面实现的。
“Content 模块” 和 “Content API” 将下面的渲染机制。安全机制和插件机制等隐藏起来,提供一个接口层。该接口目前被上层模块或者其余项目使用,内部 调用者包括 Chromium 浏览器、 Content Shell 等、外部包括 CEF (Chromium Embedded Framework)、Opera 浏览器等。
“Chromium 浏览器” 和 ”Content Shell“ 是构建在 Content API 之上的两个 ”浏览器“,Chromium 具备浏览器完整的功能,也就是咱们编译出来能看到的浏览器式样。而 ”Content Shell“ 是使用 Content API 来包装的一层简单的 ”壳“,可是它也是一个简单的 ”浏览器“,用户可使用 Content 模块来渲染和显示网页内容。Content Shell 的做用很明显,其一能够用来测试 Content 模块不少功能的正确性,例如渲染、硬件加速等。其二是一个参考,能够被不少外部的项目参考来开发基于 ”Content API“ 的浏览器或者各类类型的项目。
在 Android 系统上, Content Shell 的做用更大,这是由于同它并排的左侧的 ”Chromium 浏览器“ 部分的代码根本就没有开源,这直接致使开发者只能依赖 Content Shell。
”Android WebView“ 是为了知足 Android 系统上的 WebView 而设计的,其思想是利用 Chromium 的实现来替换原来 Android 系统默认的 WebView。
多进程模型至少带来了三点好处:
一、避免因单个页面不响应或者崩溃而影响整个浏览器的稳定性
二、当第三方插件崩溃时不会影响页面或者浏览器的稳定性,这时由于第三方插件也被使用单独的进程来运行
三、它方便了安全模型的实施,也就是说沙箱模型是基于多进程架构的。
Chromium 浏览器主要包括如下进程类型:
一、Browser 进程:浏览器的主进程,负责浏览器界面的显示、各个页面的管理、是全部其余类型进程的祖先、负责它们的建立和销毁等工做,它有且仅有一个。
二、Renderer 进程:网页的渲染进程,负责页面的渲染工做, Blink/WebKit 的渲染工做主要在这个进程中完成,可能有多个,可是 Renderer 进程的数量与用户打开的网页数量不必定一致,Chromium 设计了灵活的机制,容许用户配置。此外,在沙箱模型启动的状况下,该进程可能会发生一些改变。
三、NPAPI 插件进程:该进程是为 NPAPI 类型的插件而建立的。其建立的基本原则是每种类型的插件只会被建立一次,并且仅当使用时才会被建立。当有多个网页须要使用同一种类型的插件的时候,例如不少网页须要使用 Flash 插件, Flash 插件的进程会为每一个使用者建立一个实例,因此插件进程是被共享的。
四、GPU 进程: 最多只有一个,当且仅当 GPU 硬件加速打开的时候才会被建立,主要用于对 3D 图形加速调用的实现。
五、Pepper 插件进程:同 NPAPI 插件进程,不一样的是为 Pepper 插件而建立的进程。
六、其余类型的进程:图中还有一些其余类型的进程没有描述出来,例如 Linux 下的 “Zygote” 进程,Renderer 进程其实都是由它建立而来。另一个就是名为 “Sandbox” 的准备进程,这在安全机制中做进一步的介绍。
对于桌面系统(Windows、Liunx、Mac OS)中的 Chormium 的浏览器,它们的进程模型总结后包括如下一些特征:
一、Browser 进程和页面的渲染分开的,这保证了页面的渲染致使的崩溃不会致使浏览器主界面的崩溃。
二、每一个网页是独立的进程,这保证了页面之间相互不影响。
三、插件进程也是独立的,插件自己的问题不会影响浏览器主界面和网页
四、GPU 硬件加速进程也是独立的。
Browser 进程和 Render 进程是如何利用 WebKit 渲染网页的,这其中的代码层次由图 3-6 给出。
最下面的就是 WebKit 接口层,通常基于 WebKit 接口层的浏览器直接在上面构建,而没有引入复杂的多进程架构。
而后,在 WebKit 接口层上面就是 Chromium 基于 WebKit 的接口层而引入黏附层,它的出现主要是由于 Chromium 中的一些类型和 WebKit 内部不一致,因此须要一个简单的桥接层。
再上面的就是 Renderer,它主要是处理进程间通讯,接受来自Browser 进程的请求,并调用相应的 WebKit 接口层,同时,将 WebKit 的处理结果发送回去,上面这些介绍的层都是在 Renderer 进程中工做的。
下面就进入了 Browser 进程,与 Renderer 进程相对应的就是 RendererHost, 其目的也是处理同 Renderer 进程之间的通讯。不过 RendererHost 是给 Renderer 进程发送请求并接收来自 Renderer 进程的结果。
Web Contents 表示的就是网页的内容,由于网页可能有多个须要绘制的内容,例如弹出的对话框内容,因此这里是 “Contents”。它同时包括显示网页内容的一个子窗口(在桌面系统上),这个子窗口最后被嵌入浏览器的用户界面,做为它的一个标签页。
每一个进程内部都有不少的线程。
多线程的主要目的就是为了保持用户界面的高响应度,保证 UI 线程(Browser进程中的主线程)不会被任何其余费用时的操做阻碍从而影响了对用户操做的响应。这些费时的其余操做不少,例如本地文件读写、socket 读写、数据库操做等。
既然文件读写等会阻碍其余操做,因此把它们放在单独的线程里面本身忙或者等待去吧。而在 Renderer 进程中,Chromium 则不让其余操做阻止渲染线程的快速执行。为了利用多核的优点,Chromium 将渲染过程管线化,这样可让渲染的阶段在不一样的线程执行。
网页的加载和渲染过程在图中模型下的基本工做方式如如下步骤:
一、Browser 进程收到用户的请求,首先由 UI 线程处理,并且将相应的任务转给 IO 线程,它随即将该任务传递给 Renderer 进程。
二、Renderer 进程的 IO 线程通过简单解释后交给渲染线程。渲染线程接受请求,加载网页并渲染网页,这其中可能须要 Browser 进程获取资源和须要 GPU 进程来帮助渲染,最后 Renderer 进程将结果由 IO 线程传递给 Browser 进程。
三、最后 Renderer 进程接收到结果并将结果绘制出来。
Content 接口不只提供了一层对多进程进行渲染的抽象接口,并且它从诞生以来一个重要的目标就是要支持全部的 HTML5 功能、GPU 硬件加速功能和沙箱机制,这可让 Content 接口的使用都们不须要不少的工做便可获得很强大的能力。
Content 接口按照功能分红六个部分。每一个部分的接口通常也能够分红两类,第一类是嵌入者(embedder,这里能够是 Chromium 浏览器、CEF3 和 Content Shell )调用的接口,另外一类是嵌入者应该实现的回调接口,被 Content 接口的内部实现所调用,用来参与具体实现的逻辑或者事件的监听等。
相比于狭义的 WebKit ,WebKit2 是一套全新的结构和接口,而不是一个简单的升级版。它的主要目的和思想同 Chromium 相似,就是将渲染过程放在单独的进程中来完成,独立于用户界面。
依旧是自底向上介绍,WebKit2 中也引入了插件进程,并且它还引入了网络进程。图中的 “Web 进程” 对应于 Chromium 中的 Renderer 进程,主要是渲染网页。在这之上的是 “UI 进程”,它对应于 Chromium 中的 Browser 进程。接口就是暴露在该进程中,应用程序只须要调用该接口便可。其中 “应用程序 ” 指的是浏览器或者任何使用该接口的程序。
但愿本文对你有点帮助。
对 全栈开发 有兴趣的朋友能够扫下方二维码关注个人公众号 —— 爱写bugger的阿拉斯加
分享 web 开发相关的技术文章,热点资源,全栈程序员的成长之路
陛下...看完奏折,点个赞再走吧!