您现在的位置是:首页 >其他 >Chromium 多进程架构(Multi-process Architecture)网站首页其他

Chromium 多进程架构(Multi-process Architecture)

qichengzong_right 2025-04-30 12:01:02
简介Chromium 多进程架构(Multi-process Architecture)

多进程架构(Multi-process Architecture)

这份文档对 Chromium 的高级架构,以及它在多种进程类型间的划分方式进行了阐述。

挑战

构建一款永不会崩溃或挂起的渲染引擎,近乎天方夜谭;同样,打造一个绝对安全的渲染引擎,也几乎是不可能完成的任务。

大约在 2006 年前后,网络浏览器在某些层面与过往的单用户、协同多任务操作系统1存在相似之处。在这类操作系统里,一个运行异常的应用程序,便可能致使整个系统崩溃;与之类似,在网络浏览器中,一个表现异常的网页,也有同样的 “破坏力”。只需渲染引擎或插件出现一处漏洞,就足以让整个浏览器以及所有正在运行的标签页崩溃。

现代操作系统之所以更为稳健可靠,是因为它们把应用程序置于相互隔离的独立进程之中。某个应用程序崩溃,一般不会危及其他应用程序的正常运行,也不会破坏操作系统的完整性,而且每个用户对其他用户数据的访问权限也受到严格限制。Chromium 的架构,正是致力于实现这种更具稳健性的设计理念 。

概述

Chromium采用多进程架构,以此保护整个应用程序,使其免受渲染引擎或其他组件出现的错误与故障影响。同时,它对每个渲染引擎进程访问其他进程以及系统其余部分的权限加以限制。从某些层面而言,这就如同操作系统中的内存保护与访问控制机制,为网页浏览带来了诸多益处。

把运行用户界面(UI),同时负责管理渲染器以及其他进程的主进程,称作“浏览器进程”或者“browser”。与之类似,处理网页内容的进程被叫做“渲染器进程”或者“renderers”。这些渲染器运用 Blink2 开源布局引擎,对 HTML 进行解析与布局。

在这里插入图片描述

管理渲染进程

每个渲染器进程都有一个全局的 RenderProcess 对象,该对象负责管理与父浏览器进程的通信并维护全局状态。浏览器为每个渲染器进程维护一个相应的 RenderProcessHost,它管理浏览器状态并处理与渲染器之间的通信事务。浏览器和渲染器使用 Mojo4Chromium 的传统 IPC(进程间通信)系统进行通信。

管理帧和文档

每个渲染器进程都有一个或多个 RenderFrame 对象,这些对象与承载内容的文档框架一一对应。浏览器进程中的相应 RenderFrameHost 管理与该文档相关的状态。每个 RenderFrame 都会被分配一个路由 ID,用于区分同一渲染器中的多个文档或框架。这些 ID 在一个渲染器内部是唯一的,但在浏览器中不是唯一的,所以识别一个框架需要同时有一个 RenderProcessHost 和一个路由 ID。从浏览器到渲染器中的特定文档的通信是通过这些 RenderFrameHost 对象完成的,它们知道如何通过 Mojo 或传统的 IPC 发送消息。

RenderView和RenderFrame的关系

在 Chromium 中,RenderViewRenderFrame 是两个紧密相连且有着明显演进脉络的关键概念,RenderFrame 是在 RenderView 基础上为适应现代网页复杂结构而发展起来的,RenderView 像是一个容器,可包含多个 RenderFrame,负责协调管理它们之间的交互,而 RenderFrame 则作为独立的渲染单元,承担着具体的渲染任务,如处理自身的渲染逻辑、JavaScript 执行和事件处理等,RenderFrame 取代了 RenderView 成为渲染管理的核心,使 Chromium 能更细粒度、更灵活高效地进行网页渲染工作,二者协同工作,共同提升了 Chromium 渲染架构应对复杂网页内容和用户需求的能力。RenderFrameHostRenderViewHost 的关系与之类似。

组件和接口

在渲染器进程中:

  • RenderProcess 负责处理与浏览器中对应 RenderProcessHost 的 Mojo 配置以及传统 IPC 通信。每个渲染器进程仅存在一个 RenderProcess 对象。
  • RenderFrame 对象借助 Mojo 与浏览器进程里对应的 RenderFrameHost 以及 Blink 层展开通信。该对象代表着选项卡或子框架内一个网页文档的内容。

在浏览器进程中:

  • RenderProcessHost 对象代表着单个浏览器与渲染器 IPC 连接的浏览器端。于浏览器进程而言,每个渲染器进程都对应一个 RenderProcessHost
  • RenderFrameHost 对象对与 RenderFrame 的通信进行封装,RenderWidgetHost 则负责处理浏览器中 RenderWidget5 的输入与绘制。

若要深入了解这种嵌入方式的具体工作原理,请查阅 “How Chromium displays web pages design”(Chromium 如何显示网页设计)文档。

渲染进程共享

通常情况下,每一个新窗口或标签页都会在全新的进程中打开。浏览器会生成一个新进程,并指令其创建一个独立的 RenderFrame,而这个 RenderFrame 或许会在页面中创建更多的 iframe(这些 iframe 有可能位于不同进程中)。

在某些情形下,于标签页或窗口之间共享渲染进程是必要的,或者是较为理想的做法。举例来讲,一个网络应用可通过 window.open 来创建另一个窗口,若新文档与原文档属于同一来源,那么它就必须共享相同的进程。此外,倘若进程总数过多,Chromium 也会采取策略,将新标签页分配到现有的进程当中。这些考量因素与策略在 “进程模型(Process Models)” 文档中有详细阐述。

崩溃或行为一场渲染器监测

每一个与浏览器进程建立的 Mojo 或 IPC 连接都会对进程句柄进行实时监视。一旦这些句柄接收到信号,那就意味着渲染器进程已然崩溃,此时,受影响的标签页和框架会及时收到崩溃通知。Chromium 会展示出 “悲伤的标签页” 或 “悲伤的框架” 图像,以此告知用户渲染器已崩溃。用户可以通过按下重新加载按钮,或者发起一次新的导航操作来重新加载页面。当这种崩溃状况出现时,Chromium 会检测到当前不存在渲染器进程,进而创建一个新的渲染器进程。

渲染器沙箱化

由于渲染器在独立进程中运行,这使我们有契机借助沙箱化手段,对其系统资源访问权限加以限制。举例来说,我们能够确保渲染器仅能通过 Chromium 的网络服务来访问网络。同理,我们还可以利用主机操作系统的内置权限,限制其对文件系统的访问,或者限制其对用户显示与输入的访问。这些限制措施在很大程度上约束了遭受攻击的渲染器进程可能造成的危害,大幅限制了受损渲染器进程所能实现的破坏性功能。

内存回收

当渲染器在独立进程中运行时,将隐藏标签页视作低优先级任务就变得轻而易举。在 Windows 系统里,通常情况下,最小化进程的内存会自动被纳入 “可用内存” 池。当内存不足时,Windows 会在置换高优先级内存之前,先把这些内存交换到磁盘上,这有利于提高用户可见程序的响应速度。我们可以把同样的原理应用到隐藏标签页上。当一个渲染进程没有顶级标签页时,我们可以缩减该进程的 “工作集” 大小,以此作为一种提示,让系统在必要时优先将这部分内存交换到磁盘。不过,我们发现,当用户在两个标签页之间切换时,减小工作集大小会降低标签页的切换性能,所以我们采用逐步释放内存的方式。这意味着如果用户切回到最近使用过的标签页,该标签页的内存更有可能被重新调入内存,而相比之下,较少使用的标签页则可能性较低。对于那些有足够内存运行所有程序的用户而言,他们根本不会察觉到这一过程:因为只有在有需要时,Windows 才会实际回收这些数据,所以在内存充足的情况下,不会产生性能损耗。

这有助于我们在内存不足的情况下,实现更优化的内存占用。与极少使用的后台标签页相关的内存能够被完整地交换出去,而前台标签页的数据则可以完全加载到内存中。反观单进程浏览器,所有标签页的数据会杂乱地分布在其内存中,无法如此清晰地将已使用和未使用的数据分离开,进而造成内存和性能的浪费。

其他类型的进程

Chromium 还将众多其他组件拆解为独立进程,这一过程有时会以平台特定的方式开展。比如,如今它设有独立的 GPU 进程、网络服务以及存储服务。经过沙箱化处理的实用程序进程,也会被应用于小型任务或存在风险的任务中,以此作为践行安全 “二原则” 的一种途径。

链接


  1. 单用户、协同多任务操作系统允许单个用户在同一时间内运行多个程序,这些程序可协同工作,共享系统资源,如内存、CPU 等,用户能在不同程序间灵活切换和交互,提高了工作效率,比如用户可以一边使用文字处理软件编辑文档,一边播放音乐。然而,它也存在一些缺点,由于系统资源是共享的,一个程序出现故障或异常占用过多资源,可能会导致整个系统运行缓慢甚至崩溃,而且单用户的设计意味着多用户使用场景下缺乏用户权限管理等功能,无法满足多用户不同权限和数据隔离等需求,安全性和管理性相对较弱。 ↩︎

  2. Blink 是一种由谷歌从 WebKit3 分叉而来的开源浏览器渲染引擎,它继承了 WebKit 的大量代码基础,在 HTML 解析、CSS 渲染等方面与 WebKit 有相似原理,但又引入了多进程架构等创新技术以提升浏览器的稳定性、安全性和性能,主要应用于谷歌 Chrome 浏览器、基于 Chromium 开发的浏览器以及 Android 系统的浏览器等,在现代网络浏览和应用开发领域占据重要地位。 ↩︎

  3. WebKit 是一个开源的浏览器排版引擎,最初于 2001 年由苹果公司从 KDE 的 KHTML 渲染引擎衍生而来,用于开发 Safari 浏览器,它遵循 W3C 等网页标准,具备强大的 HTML、CSS 解析及渲染能力,以高效、稳定和良好的兼容性著称,被广泛应用于苹果的 iOS 和 macOS 系统的浏览器及众多应用程序中,同时也是三星浏览器等其他一些浏览器的技术基础,在推动网页技术发展和提升用户网络浏览体验方面发挥着重要作用。
    分享Webkit和Blink在渲染引擎方面有哪些具体的差异?Blink是如何从WebKit引擎分叉出来的?介绍一下WebKit的开源许可证及使用限制 ↩︎

  4. Chromium 的 Mojo 是一种基于消息传递的跨进程通信(IPC)机制和相关的编程框架,旨在为 Chromium 项目提供更高效、灵活和可扩展的进程间通信方式。它采用了现代的异步编程模型,能够支持多种不同类型的数据传输,包括自定义的复杂数据结构等,并且具有良好的安全性和隔离性,有助于增强 Chromium 架构中不同进程之间交互的稳定性和可靠性。Mojo 还提供了一套丰富的 API,方便开发者在 Chromium 的不同组件和进程之间进行通信和协作,使得各个模块可以更好地协同工作,从而提升整个浏览器系统的性能和功能。 ↩︎

  5. 在 Chromium 中,RenderWidget 是渲染进程里负责实际渲染内容的对象,承担着绘制网页元素、处理动画效果等具体渲染任务,是网页视觉呈现的执行者;而 RenderWidgetHost 处于浏览器进程,作为 RenderWidget 在浏览器进程的代理,它负责管理和协调 RenderWidget 的行为,处理来自用户的输入事件(如鼠标点击、滚动等)并传递给 RenderWidget,同时将 RenderWidget 的渲染结果反馈到浏览器界面进行显示,二者紧密协作,确保网页内容能在浏览器中正确渲染和交互。 ↩︎

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。