How Blink Works

Blink 是 Chrome 的渲染引擎,负责实现Web平台规范,内嵌V8执行JavaScript。它采用多进程架构,主线程处理大部分任务,使用PartitionAlloc和Oilpan进行内存管理。本文概述了Blink的进程/线程结构、内存管理、Web IDL绑定等内容,帮助开发者理解其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

How Blink Works

TL;NR

在 Blink 上开发绝非易事。对于新接触 Blink的开发者来说,要实现一个高效的渲染引擎,需要了解大量Blink特有的概念和编码约定。对于经验丰富的开发者来说亦非易事,因为 Blink 非常庞大,对性能、内存和安全性极为敏感。
本文从全局概述了 “Blink 是如何工作的”,希望有助于开发者快速熟悉Blink的架构:

  • 本文并非Blink详细架构与编码规范的开发手册(这些内容可能会变化或过时)。相反地,本文简明扼要地介绍了短期内不会变更的Blink基本原理,并提供了可以进一步阅读的资源(如果你想了解更多的话)
  • 本文不解释特定功能(e.g. ServiceWorkers, editing),相反地,本文解释了代码中广泛使用的基本功能(e.g. 内容管理, V8 APIs).

关于Blink开发的更多内容, 参考这里 Chromium wiki page

Blink 做了什么

Blink 是web平台的渲染引擎。简单地说,Blink 实现了浏览器 tab 内的所有内容的渲染:

  • 实现web平台规范(e.g HTML标准),包括 DOM, CSS, WebIDL
  • 内嵌 V8,并执行 JavaScript
  • 向底层网络栈申请资源
  • 构建 DOM 树
  • 计算样式与布局
  • 内嵌 Chrome Compositor,并绘图

通过 content public APIs , 很多客户端嵌入了 Blink, 如 Chromium, Android WebView, Opera 等.
在这里插入图片描述

从代码的角度来看,Blink 即 //third_party/blink/ ;从工程(project)的角度来看,Blink 即实现Web平台功能的工程。实现Web平台功能的代码分布在 //third_party/blink/, //content/renderer/, //content/browser/ 及其它地方。

进程/线程架构

进程

Chromium 是多进程架构的。它有一个 浏览器进程(browser process) 与 N 个沙盒化的 渲染进程(renderer process),Blink 运行在 渲染进程中。
那么,N 是多少呢?为安全计,跨站点 documents 间的内存地址隔离非常重要(即站点隔离 Site Isolation)。 理论上讲,一个 渲染进程最多只应该用于一个站点。而事实上,当用户打开了太多的 tab ,或者没有足够的内存时,对 渲染进程与站点做一对一的限制就显得很繁重了。所以,多个 iframe 或从不同站点加载的 tab 可能会共享同一个渲染进程。这意味着一个 tab 内的 iframe 可能在不同的渲染进程中,而不同 tab 内的 iframe 可能在一个渲染进程中。渲染进程,iframe 与 tab 之间不存在 1:1 的映射关系

对于一个运行在沙盒中的渲染进程, Blink 需要向浏览器进程派发系统调用(e.g. 访问文件,播放媒体),以及访问用户数据(user profile data, e.g. cookie, passwords)。 这种 浏览器-渲染 进程间的通信是基于 Mojo 的(过去使用的是 Chromium IPC, 目前仍有一些地方在使用它,但该方式已被弃用)。在 Chromium 中正在进行服务化(Servicification),并将浏览器进程视为一组 “服务” 的集合。从 BlinK 的角度来看,它只需要使用 Mojo 与服务和浏览器进程交流。
在这里插入图片描述

若想了解更多:

线程

一个渲染进程会创建多少个线程呢?
Blink 有一个主线程(main thread), N 个工作线程(worker thread) 以及一堆内部线程(internal thread)。
几乎所有重要的事件都发生在主线程内: 所有的JavsScript(workers 除外),DOM, CSS, 样式与布局计算都运行在主线程内。Blink 经过高度优化以使主线程性能最大化。
Blink 会创建多个工作线程以运行 Web Workers, ServiceWorkers 以及 Worklets.
Blink 及 V8 会创建多个内部线程来处理 网络音频、数据库、GC 等。
对于进程间通信,你必须使用 PostTask APIs 来传递消息。除非个别地方出于性能原因,我们不鼓励使用共享内存编程。这就是为什么你很少在 Blink 代码内见到互斥锁。
在这里插入图片描述

若想了解更多:

  • Blink 中的线程编程: platform/wtf/ThreadProgrammingInBlink.md
  • Workers

Initialization & finalization

Blink 使用 BlinkInitializer::Initialize() 初始化。它必须在任何 Blink 代码调用前执行。
但 Blink 从不终结化(finalized). 比如,渲染进程会不做清理而强制退出。这一方面是基于性能原因。另一方面,优雅有序地完全清理渲染进程的内容是真的难(也不值这么做)。

目录结构

Content public API 以及 Blink public API

Content public API 是使程序能嵌入渲染引擎的 API 层。它是暴露给其它程序的API, 须小心维护。
Blink public API 是 //third_party/blink/ 向 chromium 提供功能的 API 层。这是从Webkit 继承而来的 API. 在 Webkit 时代,Chromium 和 Safari 共享 Webkit, 所以这些API 需要向 Chromium 和 Safari 提供功能,而现在 //third_party/blink/ 只有 Chromium 在用,所以它不再重要了。我们现在正在消减 Blink public API, 将 web平台的代码从 Chromium 移到 Blink 中(即 “Onion Soup Project”)
在这里插入图片描述

目录结构及依赖

//third_party/blink 有如下目录:

  • platform/ : Blink 底层功能的集合,它们是从 core/ 中分离出来的, e.g. geometry 与 graphics utils
  • core/modules/ : 所有 web 平台的功能实现都在这里。 core/ 实现了与 DOM 紧耦合的功能, modules/ 则实现了更多自包含的功能, e.g. webaudio, indexedBD
  • bindings/core/bindings/modules/ : 理论上 bindings/core/core/ 的一部分, bindings/modules/modules/ 的一部分。重度使用 V8 API 的文件放在这里
  • controller/ : 使用 core/modules/ 的上层库。 e.g. devtools 前端。

这个文档有更详细的介绍

依赖顺序如下:

  • Chromium
  • controller/
  • modules/bindings/modules/
  • core/bindings/core/
  • pl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值