Blink 架构
TL;DR
Blink是Chromium的Web渲染引擎,它不只是布局引擎,它实现了一个浏览器tab内所有关于渲染的内容:
- Web平台规范(HTML,CSS,DOM,SVG,…)
- 内嵌V8来运行JavaScript
- 网络相关资源
- DOM树构建
- 样式计算与布局
- Chrome Compositor(AKA:CC) 与图形绘制
Blink 也通过API可嵌入到不同环境中,例如 Chromium,Android webview。
Blink 在 code base 中位于//third_party/blink/,从项目角度看,Blink 表示所有实现了 Web 特性的代码,例如//third_party/blink/, //content/renderer/, //content/browser/,以及其他位置。
进程架构
Chromium 是一个 多进程架构 的浏览器,包含一个browser进程及若干个在沙箱环境下的 render 进程,Blink 运行在每一个 render 进程中。
理论上出于安全考虑,每一个站点(或者说每一个tab)都有自己的唯一一个 render 进程,也就是说 render 进程是站点(tab级别)独有且独立的。但当用户有很多 tab 或内存不足的情况下,render 进程可能会在多个 iframe 或不同站点(tab)中共享。这表示页面中的 iframe 可能会存在不同于页面的 render 进程,或者多个页面中的 iframe 共享同一渲染进程。
对于在沙箱环境中运行的 render 进程,blink 会向 browser 进程请求系统调用,例如文件/音视频/访问用户数据等,这些调用通过 Mojo(一种 IPC 机制)实现,概念上类似于豆瓣的 pidl。(Chromium IPC是过去的实现,并且现在有些地方仍在使用,但它已经废弃)。
Chromium 正在进行服务化改造。
线程模型
Blink有一个主线程,若干个 Worker 线程及内部线程。主线程包含几乎所有的重要工作,例如 JavaScript(除了 WebWorker ),dom,css,样式计算与布局,可以近似看作一个单线程架构。对于 WebWorker,ServiceWorker,Worklet这三种场景blink会创建worker线程。同时 Blink 及 v8 也会创建自己的内部线程(子线程)来处理 WebAudio,GC,database等功能。
进程间通信使用 PostTask API,除非因为性能原因,进程间通信不使用共享内存编程。
Blink 初始化方法
1BlinkInitializer::Initialize();
目录结构
blink/common与blink/public/common运行在browser进程。
blink/renderer是blink的核心功能,它包含绝大部分web功能实现,并且运行在render进程。
-
renderer
- core - web规范实现,由于历史原因,core实现非常复杂,所以可以看作一个整体
- modules - 具有良好定义,且功能独立的modules(除core外的功能),每一个module都是web的一个独立功能
- platform - blink低级功能集合
注意,从web规范没有core/module/platform的概念,这三种目录只是出于代码组织及功能划分原因创建的。HTML,CSS,DOM等web核心紧密结合的规范放在core中,依赖于core的功能放在modules中,core依赖的功能放在platform中。
- bindings - v8&dom binding
- controller - controller不负责web功能实现,它是控制blink行为的基础结构。
- build - blink构建脚本
依赖结构
WTF
WTF是blink的基础库,包含容器、字符串、内存、线程等功能
页面级概念
- Page - 一个 Page 相当于一个 tab(概念上的 tab )
- Frame - 一个 Frame 是一个 frame(包含主 frame 以及 iframe ),每一个 Page 包含一个或多个 frame
- DOMWindow - JavaScript 中的 window 对象,每个 Frame 中包含一个 DOMWindow
- Document - JavaScript 中的 window.document 对象,每个 Frame 中包含一个 Document
- ExecutionContext - 一个 Document 或 worker 的抽象