浏览器的进程架构

225 阅读10分钟

平安喜乐

本文乃学习过程中的一些产物,讲的不好的地方还请指正

当我们打开浏览器Chrome的任务管理器,我们会发现在浏览器中运行着许许多多的进程,那他们之间是如何共同发挥作用的呢?浏览器为什么需要这么多进程?

在深入这些问题之前,我们需要了解一些概念

进程和线程

进程

进程是操作系统中的一个基本概念,它表示正在执行的程序的实例。一个进程就是一个程序的运行实例。 详细解释就是,启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主进程,我们把这样的一个运行环境叫做进程。

进程可以请求操作系统启动另一个进程来执行不同的任务。此时,内存中的不同部分会分给新进程。如果两个进程需要对话,他们可以通过进程间通信IPC)来进行。许多应用都是这样设计的,所以如果一个工作进程失去响应,该进程就可以在不停止应用程序不同部分的其他进程运行的情况下重新启动。

线程

在进程中,如果只有进程去处理所有任务,那么任务只能线性处理而不能并行处理,会大大的影响效率,如图所示。

线程不能单独存在,必须由进程来启动和管理。

线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。

线程和进程有以下一些显著特点。

  • 进程中的任一线程执行出错,都会导致整个进程的崩溃。
  • 线程之间共享进程中的数据。
  • 当一个进程关闭之后,操作系统会回收进程所占用的内存。

当一个进程退出时,操作系统会回收该进程所申请的所有资源;即使其中任意线程因为操作不当导致内存泄漏,当进程退出时,这些内存也会被正确回收。 比如之前的 IE 浏览器,支持很多插件,而这些插件很容易导致内存泄漏,这意味着只要浏览器开着,内存占用就有可能会越来越多,但是当关闭浏览器进程时,这些内存就都会被系统回收掉。

  • 进程之间的内容相互隔离。

进程隔离是为保护操作系统中进程互不干扰的技术,每一个进程只能访问自己占有的数据,也就避免出现进程 A 写入数据到进程 B 的情况。正是因为进程之间的数据是严格隔离的,所以一个进程如果崩溃了,或者挂起了,是不会影响到其他进程的。如果进程之间需要进行数据的通信,这时候,就需要使用用于进程间通信(IPC)的机制了。

在了解了基本概念之后,我们来一起看一下浏览器的进程架构。

浏览器的进程架构

单进程架构

顾名思义,单进程浏览器是指浏览器的所有功能模块都是运行在同一个进程中,这些模块包含了网络、插件、JavaScript运行环境、渲染引擎和页面等。在2007年之前,市面上的浏览器都是单进程的。

这些功能模块统一运行在一个进程中,导致单进程浏览器出现不稳定、不流畅和不安全等问题

不稳定

早起浏览器需要借助插件来实现诸如Web视频、Web游戏等各种强大的功能,但是插件是最容易出问题的模块,并且还运行在浏览器进程中,所以一个插件的意外崩溃会引起整个浏览器的崩溃。

除了插件之外,渲染引擎模块也是不稳定的,通常一些复杂的 JavaScript 代码就有可能引起渲染引擎模块的崩溃。和插件一样,渲染引擎的崩溃也会导致整个浏览器的崩溃。

不流畅

在浏览器运行中,页面的渲染模块、JavaScript执行环境以及插件都是运行在同一个线程(页面线程)下面,这就意味着同一时刻只能有一个模块可以执行。如果有高耗时的js脚本执行,那么就会独占整个线程。这样就会导致整个浏览器失去相应,变卡顿。

除了上述脚本或者插件会让单进程浏览器变卡顿外,页面的内存泄露也是单进程变慢的一个重要原因。通常浏览器的内核都是非常复杂的,运行一个复杂点的页面再关闭页面,会存在内存不能完全回收的情况,这样导致的问题是使用时间越长,内存占用越高,浏览器会变得越慢。

不安全

插件和页面脚本是导致安全问题的主要原因。插件可以使用 C/C++等代码编写,通过插件可以回去到操作系统的任意资源,这意味着恶意插件的开发成本将大幅降低,此外,页面脚本也可以通过浏览器的漏洞来获取系统权限,引发安全问题。

为了解决上述问题,浏览器进入了“多进程时代”。

早期多进程架构

在2008年,Chrome发布了最早的多进程架构

从图中,可以看出,Chrome的页面是运行在单独的渲染进程中的,同时页面里的插件也是运行在单独的插件进程之中,而进程之间是通过IPC机制进行通信。

那新的多进程架构是如何解决之前的问题呢?

不稳定问题

之前我们说过,不稳定问题,主要是因为插件模块和渲染引擎模块都运行在浏览器的同一个线程中,而插件模块和渲染引擎模块很容易会出现问题导致页面线程崩溃,而线程的崩溃则会导致浏览器进程的崩溃。

那么现在从多进程架构的示例图中,可以看到这两个模块被抽离为了插件进程渲染进程,而进程之间是相互隔离的,所以当一个页面或者插件崩溃时,影响到的仅仅是当前页面进程或者插件进程,并不会影响到浏览器和其他页面,这就完美解决了上述不稳定问题。

不流畅问题

通过上面问题描述,我们可以清楚,高耗时的JS脚本执行以及页面的内存泄露会导致浏览器进程变慢。

在新的多进程架构中,每个页面都会单独运行在一个有沙箱的渲染进程中,在这个独属于自己的渲染进程中去进行JS脚本的加载,那么即使JavaScript 阻塞了渲染进程,影响到的也只是当前的渲染页面,而并不会影响浏览器和其他页面,因为其他页面的脚本是运行在它们自己的渲染进程中的。所以当我们再在 Chrome 中运行上面那个死循环的脚本时,没有响应的仅仅是当前的页面。

对于内存泄漏的解决方法那就更简单了,因为当关闭一个页面时,整个渲染进程也会被关闭,之后该进程所占用的内存都会被系统回收,这样就轻松解决了浏览器页面的内存泄漏问题。

不安全问题

采用多进程架构的额外好处是可以使用安全沙箱,你可以把沙箱看成是操作系统给进程上了一把锁,沙箱里面的程序可以运行,但是不能在你的硬盘上写入任何数据,也不能在敏感位置读取任何数据,例如你的文档和桌面。Chrome 把插件进程和渲染进程锁在沙箱里面,这样即使在渲染进程或者插件进程里面执行了恶意程序,恶意程序也无法突破沙箱去获取系统权限。

多进程架构演变

在经过一段时间的演变,浏览器的多进程架构又有了新的改变

演变后的多进程架构将GPU,网络进程等再次独立出来。

  • 浏览器主进程: 负责界面显示、用户交互、子进程管理等
  • 渲染进程: 渲染进程复杂将HTML、CSS和JavaScript转换为可交互的网页,其中包含(Webkit 排版引擎, JavaScript引擎---V8),默认情况下每打开一个Tab页签,Chrome都会为其创建一个渲染进程。
  • GPU进程: 最初是为了3D CSS的效果,现在也用来绘制UI界面。
  • 网络进程: 负责页面的网络资源加载。
  • 插件进程:主要负责插件的运行,独立是为了防止插件崩溃对浏览器和其他页面造成影响。

那么说了这么多浏览器多进程架构的优点,那么它有什么缺点吗

  • 更高的资源占用: 因为每个进程都会包含公共基础结构的副本(如 JavaScript 运行环境),这就意味着浏览器会消耗更多的内存资源。
  • 更复杂的体系架构: 浏览器各模块之间耦合性高、扩展性差等问题,会导致现在的架构已经很难适应新的需求了。

对于上面的问题,Chrome团队提出了新的体系架构方案

目前Chrome多进程架构

其实从本文开头的那张图来看,它并不符合我们上文提到的任何一个多进程架构。

2016年,Chrome 官方团队使用“面向服务的架构”(Services Oriented Architecture,简称 SOA)的思想设计了新的 Chrome 架构。也就是说 Chrome 整体架构会朝向现代操作系统所采用的“面向服务的架构” 方向发展,原来的各种模块会被重构成独立的服务(Service),每个服务(Service)都可以在独立的进程中运行,访问服务(Service)必须使用定义好的接口,通过 IPC 来通信,从而构建一个更内聚、松耦合、易于维护和扩展的系统,更好实现 Chrome 简单、稳定、高速、安全的目标。

Chrome 最终要把 UI、数据库、文件、设备、网络等模块重构为基础服务,类似操作系统底层服务。

同时 Chrome 还提供灵活的弹性架构,在强大性能设备上会以多进程的方式运行基础服务,但是如果在资源受限的设备上(如下图),Chrome 会将很多服务整合到一个进程中,从而节省内存占用。

结语

祝,诸君武运昌隆。

资料

浏览器原理:多进程架构

Chrome架构:仅仅打开了1个页面,为什么有4个进程?

浏览器简史及其核心原理详解:47 张图带你走进浏览器的世界

感谢以上大佬的文章,推荐阅读