Chromium的多进程架构

Chromium的多进程架构

问题:

创造一个从来不会崩溃或者挂起的渲染引擎是几乎不可能的。同样,创造一个绝对安全的渲染引擎也非常的困难。

从某些方面说,现在的浏览器就像早期的单用户共享多任务操作系统一样。一个应用程序出错可能导致整个系统的崩溃,现代浏览器的一个tab也一样。例如,一个页面或者插件的bug可能导致整个浏览器的崩溃。

现代操作系统是更健壮的,它会把应用程序分开隔离到不同的进程中。一个程序崩溃并不会对其它程序或整个系统造成影响,并且每个用户的访问其他用户的数据是受限制的。

架构总揽:

对于每个浏览器的tab,我们分别使用不同的进程,这样可以避免渲染引擎出错导致整个浏览器的崩溃。我们限制每个渲染引擎进程相互之间以及对系统其他部分的访问。这样给浏览器带来的好处就像内存地址空间隔离和访问控制给操作系统带来的好处一样。
       我们在主进程显示UI,并像管理“浏览器进程”或者“浏览器”一样管理tab和插件。同样,每个tab对应的进程叫做“渲染进程”或者“渲染器”。每个渲染器使用WebKit作为布局引擎,解析并渲染HTML。

Chromium架构

管理渲染进程

每个渲染进程都有一个全局的RenderProcess对象负责和当前浏览器进程之间的通信,并保存全局状态。 对应的,对于每一个渲染进程浏览器维护一个RenderProcessHost,它用来管理浏览器状态以及和渲染进程通信。浏览器和渲染器之间的通信通过Chromium的IPC系统。

管理View视图

每个render进程都包含一个或多个被RenderProcess管理的RenderView对象,每个RenderView和一个Tab下的内容相对应。在RenderProcess相对应的RenderProcessHost中,包含了与每个RenderView相对应的RenderViewHost。每个View都会被赋予一个在其renderer中唯一的一个ID。这些ID在一个render进程中是唯一的,但在整个浏览器中是不一定的。所以确定一个View需要一个RenderProcessHost和一个View ID。当浏览器和某一个特定的Tab页内容通信时,需要这些RenderViewHost对象通过它们的RenderProcessHost发送消息给相对应的RenderProcess中,最终传递给它的RenderView。

组件和接口

在渲染进程中:

l  RenderProcess和浏览器进程中一个对应的RenderProcessHost通过IPC通信。每一个渲染进程有唯一一个RenderProcess。

l  RenderView对象和浏览器进程中对应的RenderViewHost进行通信(通过RenderProcess)。这个对象代表每个Tab页和弹出窗口的网页内容。

在浏览器进程中:

l  Browser对象代表最顶层的浏览器窗口。

l  RenderProcessHost代表浏览器端的一个和渲染进程之间的IPC连接。在浏览器中,一个RenderProcessHost对应一个渲染器进程。

l  RenderViewHost封装和远端RenderView之间的通信,RenderWidgetHost处理浏览器中RenderWidget的输入和打印。

了解更多的细节,查看How Chromium displays web pages 设计文档。

共享渲染进程

通常情况下,每个窗口或tab启动一个新的进程。浏览器会启动一个新进程并指示它创建一个RenderView对象。
       有时候必须在多个tab和window之间共享渲染进程。比如,在JavaScript使用window.open,让web应用打开一个新窗口并和他同步通信。这种情况下,新打开的窗口或tab需要重用之前的渲染进程。 在进程达到最大值的时候或者窗口已经打开相同域名的网页时,我们也需要有策略的重用之前的渲染进程。重用的策略在“Process Models”中有详细描述。

监测崩溃或渲染器的异常行为

每个通过IPC通信的浏览器进程都监测渲染进程句柄。如果句柄收到信号则表示渲染进程已经崩溃。目前为止,我们显示一个“sad tab”的图标,通知用户渲染进程崩溃。页面可以通过点击刷新按钮重新载入,或者打开一个新页面。当遇到这种情况,我们注意到它并没有重新创建一个新的process。

渲染器和沙盒

Webkit运行在一个独立的进程中,我们可能会限制他访问系统资源。例如,我们保证渲染器只可以通过其父浏览器进程访问网络。同样,我们可以用宿主操作系统提供的权限特性限制它访问磁盘文件系统。
       除了限制渲染进程访问文件系统和网络,我们也会限制它访问用户显示对象或其他对象。每一个渲染进程是运行在分开的窗口中,是用户不可见的。这样防止受到控制的渲染器打开新窗口或记录键盘输入。

内存的回收

渲染引擎运行在单独的进程中,这样可以很方便的将当前不显示的页面(进程)设置为低的优先级。通常情况下,在Windows上最小化窗口会自动将其内存放进“可用内存”池中。 在内存不足的情况下,Windows会将首先将这些内存放入交换空间,这样有助于用户可见的程序有更好的响应速度。我们也对隐藏的tab应用这种策略,对于隐藏的tab会通知操作系统在必要时优先将这些内存交换入磁盘。因为我们发现减少内存占用也会降低tab切换的性能,所以我们逐渐释放内存。这意味着,如果用户切换回最近使用过的Tab页,Tab页的内存很可能被比最近很少使用的Tab早换入内存,不过,当内存充足的时候这些都不是问题。
       这样处理有助于在内存较小的系统上获得更优的内存占用。不常使用的tab所占用的内存可以被整个交换到磁盘,当前tab的内存可以全部放在内存中。相反,单进程的浏览器将导致它的内存随机分布,无法这样明确的区分出正在使用的和未使用的内存,这样更浪费内存和性能。

插件

和fireFox风格类似的NPAPI插件运行在他们自己的进程空间,和渲染器分离。在“PluginArchitecture”中有详细描述。


原文出处:http://www.chromium.org/developers/design-documents/multi-process-architecture

猜你喜欢

转载自blog.csdn.net/NYS001/article/details/20222743