【Chrome源码阅读系列】Chrome多进程架构

这个文档描述了Chromium的顶层架构设计web

问题背景

构建一个没有crash和挂起的渲染引擎基本是不可能,构建一个彻底安全的渲染引擎也基本是不可能的。浏览器

在某些程度上,2006年左右的web浏览器就像过去单用户、多任务合做的操做系统同样。和一些操做系统里发生故障的应用可能搞挂整个系统同样,一个操做不当的web页面也会搞挂整个浏览器。一个页面或者插件的bug就可能把整个浏览器搞崩溃以致于全部页面都不可能用了。安全

现代操做系统要相对更健壮一些,由于他们把应用都拆分进了独立的进程来相互分隔。一个应用的crash一般不会影响其余应用或者操做系统,而且每一个用户和其余用户的数据访问也是有限制的。网络

架构概述

咱们给每一个浏览器tab页都使用了独立的进程来保护大部分的应用不受渲染引擎的bug和故障影响。咱们也限制来每一个渲染引擎进程访问其余渲染引擎进程或者系统的权限。这样在某种程度上就可让浏览器受益于内存保护对操做系统的访问权限。架构

咱们把运行UI、管理tab和插件进程的主进程称为“browser process”或者“broswer”。一样地,具体的tab进程被称为“render process”或者“renderer”。renderer用Blink这个开源布局引擎来解析HTML布局。
arch.png布局

管理渲染进程

每一个渲染进程都有一个全局的RenderProcess对象来管理与父browser进程的通讯,而且维护全局状态。browser维护每一个渲染进程对应的RenderProcessHost,来管理browser状态和渲染器的通讯。browser和renderers经过Chromium IPC系统进行通讯。性能

管理视图

每一个渲染进程都有一个或者更多的RenderView对象,由RenderProcess管理,对应每一个tab的内容。对应的RenderProcessHost维护一个RenderViewHost对应每一个renderer的视图。每一个视图都被分配到一个ID来在同一个renderer里区分多个view。这些ID在同一个renderer里都是惟一的,可是在browser里面不必定惟一,因此识别一个view同时须要RenderProcessHost和view ID。browser和某个具体的tab内容之间经过RenderViewHost对象,经过RenderProcessHost给RenderProcess 再定位到RenderView发送信息来进行通讯。spa

组件和接口

在渲染进程中:操作系统

  • RenderProcess处理IPC和browser进程中对应RenderProcessHost之间的通讯。每一个渲染进程中都明确地有一个RenderProcess对象。这就是browser ↔ renderer之间通讯的方式。
  • RenderView对象和browser进程中对应的RenderProcessHost进行通讯(经过RenderProcess),和咱们嵌入式的WebKit层。这个对象表明来一个web页面的内容或者一个弹出的窗口。

在浏览器进程中:插件

  • Browser对象表明一个顶层的浏览器窗口
  • RenderProcessHost对象表明浏览器侧的一个browser ↔ renderer通讯IPC链接。每一个渲染进程和浏览器进程之间都有一个RenderProcessHost对象。
  • RenderViewHost对象包含了和远端RenderView之间的通讯,RenderWidgetHost处理输入并绘制浏览器中的RenderWidget

内部更多详细的工做原理能够,能够查看 How Chromium displays web pages)设计文档

共享渲染进程

一般,每一个新的窗口或者tab都会在一个新的进程中打开。浏览器会打开一个新的进程而且建立一个单独的RenderView。
可是有的时候,在tab和window之间共享渲染进程也是必要的。一个web饮用会打开一个新的窗口而且但愿能同步的进行通讯,好比,在Javascript中使用window.open。在这种状况下,当咱们建立一个新的window或者tab的时候,咱们就须要重复利用以前window已经打开过的进程。当进程数太多的时候咱们也有一些策略来分配已经打开的渲染进程给新的tab,或者若是这个用户已经有打开过这个域名下的页面建立的进程的时候。这个策略在Process Models中。

检测crash或者故障的renderer

每一个和browser进程通讯的IPC链接都会监听process handler。若是这些handler收到消息,renderer进程有crash,那么这些tab就会被通知到crash。当前,咱们会展现一个“sad tab”到屏幕上来告诉用户渲染进程crash了。这个页面能够经过按下刷新按钮从新加载。这个时候,咱们也会通知没有进程了,须要从新建立一个进程。

渲染沙箱

针对一个独立的进程,咱们经过沙箱去限制访问系统资源的权限。好比,咱们能够经过父browser进程来保证渲染器只能访问网络。一样的,咱们也能够用操做系统内置的权限来限制它访问文件系统的权限。
除了限制渲染器访问文件系统和网络的权限,咱们还能够限制访问用户展现相关的权限。咱们运行渲染进程在一个用户不可见的独立Windows Desktop上。这防止了渲染进程打开一个新的window或者采集按键。

回收内存

让渲染器在一个独立的进程中运行,很天然的就会给隐藏的tab更低一点的优先级。一般,被下降内存的进程会自动地把内存分配到一个“可用内存”的池子里。在低内存模式下,Windows会在要切换到高优先级模块内存以前把这些内存交换到硬盘上,来使用户可见的程序能更快的响应。咱们能够应用一样的策略到隐藏的tab里。当一个渲染进程没有最高优先级的tab时,须要时咱们能够把这个进程的“working set”大小从系统内存先释放到硬盘上。由于咱们发现减小工做区域大小也会下降用户从2个tab之间切换的切换性能。可是当用户有足够的内存来运行他们的程序的时候就不会通知这个进程:Windows只有在确实须要的时候才会回收这些数据,因此当有足够的内存时不会有性能的损失。

插件和扩展

Firefox风格的NPAPI插件运行在他们本身的进程里,和renderer分离开,详细的描述在plugin architecture里。
site isolation项目提供了renderer之间更多的隔离,包括了Chrome的HTML/Javascript在独立进程中的上下文扩展。

相关文章
相关标签/搜索