chromium Multi-process Architecture

原文链接:
http://www.chromium.org/developers/design-documents/multi-process-architecture
本文档描述了Chromium的上层架构。
问题
创建一个从不崩溃或宕机的渲染引擎几乎是不可能的。
创建一个具有完美安全性的渲染引擎也几乎是不可能的。
从某些方面讲,浏览器的现状像是过去的单用户,多任务的操作系统。
在这样的操作系统中,一个行为不慎的应用程序可以导致整个操作系统无法工作,
同样的,一个行为不慎的网页也可以导致整个现代浏览器无法工作。
一个浏览器或插件bug可以让一个行为不慎的网页使整个浏览器和当前处于运行状态的所有标签页崩溃。
现代操作系统更健壮,因为现代操作系统将应用程序放在彼此隔离的单独进程中。
一个应用程序的崩溃通常不会影响其他应用程序或者整个操作系统,每个进程对其他进程数据的访问是受限制的。

架构概述
我们使用单独的进程来运行浏览器标签页,以此来阻止渲染引擎的bug和故障对整个应用程序的影响。
我们也限制渲染引擎进程对其他渲染引擎进程和系统其余部分的访问。
从某些方面讲,这种策略给浏览器带来的好处和内存保护和访问控制给操作系统带来的好处是一样的。
我们称运行UI,管理标签页和插件进程的主进程为"browser process" or "browser."
类似的,我们称运行各个单独标签页的进程为 "render processes" or "renderers."
renderers 进程使用 WebKit开源布局引擎来解析和布局HTML页面.


管理render进程
每个render进程都有一个全局的RenderProcess对象,这个对象管理render进程和browser父进程的通信,
并维护render进程的全局状态。
browser进程为每一个render进程维护一个与RenderProcess对应的RenderProcessHost对象,
RenderProcessHost对象负责管理browser进程状态,并与render进程通信。
browser进程和render进程使用Chromium的IPC系统进行通信。

管理views
每个render进程有一个或多个RenderView 对象,这些RenderView由RenderProcess管理,
对应着标签页的内容。与RenderProcess对应的RenderProcessHost维护着
RenderViewHost,RenderViewHost与render进程中的RenderView对象对应。
每个view 都有一个view ID,用来区分同一个renderer中的多个view.
这些view ID 在同一个render进程中是唯一的,但是在browser进程中不是唯一的,
所以标识一个view需要一个RenderProcessHost和一个View ID.
browser进程和某个tab 内容的通信就是通过这些RenderViewHost对象完成的。
RenderViewHost对象知道怎样通过它所关联的RenderProcessHost发消息给RenderProcess,
进而把消息传给RenderView.

组件和接口
render进程中:
RenderProcess负责处理与browser进程中对应的RenderProcessHost之间的IPC。   
每个render进程有且只有一个RenderProcess对象。 所有的browser ↔ renderer进程间通信都是这样发生的。
RenderView对象通过RenderProcess对象与它在browser进程中对应的RenderViewHost对象通信。
RenderView对象也与我们的WebKit内嵌层通信。
RenderView对象代表标签页或弹出窗口中显示的网页内容。
browser 进程中:
browser对象代表顶层浏览器窗口。
RenderProcessHost对象代表一个browser ↔ renderer IPC 连接中的browser端.
每个render进程都对应着browser进程中的一个RenderProcessHost对象。
RenderViewHost 对象封装了与远端RenderView的通信。
RenderWidgetHost负责在browser进程中处理RenderWidget的输入和绘制。
关于这种嵌入方式的工作细节,参见How Chromium displays web pages design document.

共享render进程
通常,每个新的窗口和标签页都会在一个新的进程中打开。
browser孵化一个新的进程,并指示新的进程创建一个RenderView.
有时,在不同的标签页或窗口间共享一个render进程是必要的,或者更理想的。
一个web应用打开一个期望同步通信的新窗口,比如,使用JavaScript接口window.open.
在这种情况下,当我们创建一个新的窗口或标签时,我们需要重用打开这个窗口的进程。
当进程总数太多,或者用户已经有一个进程在运行要打开的标签时,
我们也有策略可以将标签赋给一个已经存在的进程。这些策略在进程模型从有详细的描述。

检测崩溃或有异常行为的render
每一个与browser进程建立了连接的IPC connection都监视着render进程句柄.
如果这些句柄收到信号,说明render进程崩溃了,标签页会收到崩溃通知。
目前为止,我们显示一个"sad tab"屏幕通知用户render进程崩溃了。
如果按reload按钮或者重新导航到这个页面,网页会被重新加载。
当网页被重新加载时,我们注意到没有进程在运行需加载的网页,我们创建一个新的进程。

Sandboxing the renderer
由于Webkit运行在一个单独的进程中,我们有机会限制它对系统资源的访问。
例如:我们可以确保render进程只能通过它的browser父进程访问网络。
同样的,我们可以限制render进程只能使用宿主操作系统内置的权限访问文件系统。
除了可以限制render进程访问文件系统和网络外,
我们还可以限制render进程对用户显示以及显示相关对象的访问。
我们在一个单独的用户不可见的窗口“桌面”中运行render.
这可以阻止一个受损的render打开一个新的窗口或者扑捉键值。

Giving back memory
由于render运行在单独的进程中,所以认为隐藏的标签页具有较低的优先级是很自然的。
通常来讲,窗口中最小化的进程会自动将它们占用的内存放回“可用内存”池中。
在内存不足的情况下,窗口在换出具有较高优先级的内存前,会先把这部分内存换出到硬盘,
以保持用户可见的应用程序具有更好的交互性。
我们可以对隐藏标签使用同样的策略。
当一个render进程没有顶层标签时,我们可以释放这个render进程的 “工作区间”,
以此暗示操作系统可以在需要的时候优先将这个render进程的"工作区间"内存换出到硬盘上。
因为我们发现,减少工作区间的大小会影响用户在两个标签页之间切换的性能。
所以我们逐渐的释放"工作空间"内存。
这意外着如果用户切换会最近使用过的标签页,这个标签页的数据很可能是通过换页机制重新加载进内存的。
有足够内存运行他们的程序的用户完全不会注意到这个进程:
窗口只在需要的时候实际回收这些数据,所以当有足够内存时,不会影响性能。
这帮助我们在内存不足的情况下,优化内存占用。
很少使用的后台标签页占用的内存可以全部换出,以便前台标签页的数据可以全部加载到内存中。
相反的,在只有一个进程的浏览器中,所有标签页的数据随机分布在内存中,
不可能将使用的数据和不使用的数据如此清晰的隔离开,即浪费内存又浪费性能。
插件
Firefox类型的NPAPI插件运行在他们自己的进程中,与render进程相独立。关于这部分更详细的描述参见Plugin Architecture.







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值