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
### ESP8266 IO0 Pin Running Light Example Code and Tutorial For achieving a running light effect using the IO0 pin on an ESP8266, one can utilize simple GPIO control through programming with languages like MicroPython or Arduino IDE-supported C++. Below is an example of how to implement this functionality in both environments. #### Using Arduino IDE (C++) To configure the IO0 as output and create a blinking LED effect which simulates a running light when connected properly: ```cpp const int ledPin = 0; // Define digital pin 0 as output for LED connection void setup() { pinMode(ledPin, OUTPUT); // Set up the digital pin as an output. } void loop() { digitalWrite(ledPin, HIGH); // Turn the LED on by setting the voltage high. delay(1000); // Wait for a second. digitalWrite(ledPin, LOW); // Turn the LED off by setting the voltage low. delay(1000); // Wait for another second before looping again. } ``` This sketch sets the specified pin as an output that toggles between high and low states every second, causing any attached LED to blink at regular intervals[^1]. #### Using MicroPython Similarly, here's how it works within the context of MicroPython scripting environment: ```python from machine import Pin import time led = Pin(0, Pin.OUT) # Initialize the built-in LED on pin 0 as an output device while True: led.value(not led.value()) # Toggle the state of the LED time.sleep_ms(1000) # Pause execution for 1000 milliseconds ``` In this script, `machine.Pin` class allows direct manipulation over hardware pins while `time.sleep_ms()` function pauses program flow temporarily. The combination creates periodic changes in electrical signals sent out from the selected port number leading to visible flickering effects observed via external components such as LEDs. --related questions-- 1. What are other common applications for controlling GPIOs on microcontrollers? 2. How does changing resistor values affect brightness levels in LED circuits driven by microcontroller outputs? 3. Can you explain more about different timing functions available in MicroPython compared to those used in Arduino sketches? 4. Is there any difference between using internal pull-up resistors versus external ones when interfacing switches with ESP8266 modules? 5. Are there specific considerations needed when connecting multiple LEDs to single GPIO pins simultaneously on ESP devices?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值