【译】Chromium多进程架构

多进程架构

转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//Start_Here_Background_Reading/Multi-process_Architecture.html

这个文档描述了Chromium的高层架构

问题

构建一个从不会挂起或崩溃的渲染引擎几乎是不可能的。构建一个完全安全的渲染引擎也是几乎不可能的。

在某种程度上,web浏览器当前状态就像一个与过去的多任务操作系统合作的单独的用户。正如在一个这样的操作系统中的错误程序会让整个系统挂掉,所以一个错误的web页面也可以让一个现代浏览器挂掉。仅仅需要一个浏览器或插件的bug,就饿能让整个浏览器和所有正在运行的标签页停止运行。

现代操作系统更加鲁棒,因为他们把应用程序分成了彼此隔离的独立线程。一个程序中的crash通常不会影响其他程序或整个操作系统,每个用户对用户数据的访问也是有限制的。

架构概览

我们为浏览器的标签页使用独立的进程,以此保护整个应用程序免受渲染引擎中的bug和故障的伤害。我们也会限制每个渲染引擎进程的相互访问,以及他们与系统其他部分的访问。某些程度上,这为web浏览提供了内存保护,为操作系统提供了访问控制。

我们把运行UI的进程叫做主进程(main),把插件进程称为“浏览器进程”或“浏览器(Browser)”。相似的,标签页相关的进程被称作“渲染线程”或“渲染器(renderer)”。渲染器使用WebKit开源引擎来实现中断与html的布局。

管理渲染进程

每个渲染进程有一个全局的RenderProcess对象,管理它与父浏览器进程之间的通信,维护全局的状态。浏览器为每个渲染进程维护一个对应的RenderViewHost,用来管理浏览器状态,并与渲染器交流。浏览器与渲染器使用Chromium’s IPC system进行交流。

管理view

每个渲染进程有一个以上的RenderView对象,由RenderProcess管理(它与标签页的内容相关)。对应的RenderProcessHost维护一个与渲染器中每个view相关的RenderViewHost。每个view被赋予一个view ID,以区分同一个渲染器中的不同view。这些ID在每个渲染器内是唯一的,但在浏览器中不是,所以区分一个view需要一个RenderProcessHost和一个view ID。

浏览器与一个包含内容的特定标签页之间的交流是通过这些RenderViewHost对象来完成的,它们知道如何通过他们的RenderProcessHost向RenderProcess和RenderView送消息。

组件与接口

在渲染进程中:

  • RenderProcess处理与浏览器中对应的RenderProcessHost的通信。每个渲染进程就有唯一的一个RenderProcess对象。这就是所有浏览器-渲染器之间的交互发生的方式。
  • RenderView对象与它在浏览器进程中对应的RenderViewHost和我们的webkit嵌入层通信(通过RenderProcess)。这个对象代表了一个网页在标签页或一个弹出窗口的内容。

在浏览器进程中:

  • Browser对象代表了顶级浏览器窗口
  • RenderProcessHost对象代表了浏览器端浏览器的与渲染器的IPC连接。在浏览器进程里,每个渲染进程有一个RenderProcessHost对象。
  • RenderViewHost对象封装了与远端浏览器的交流,RenderWidgetHost处理输入并在浏览器中为RenderWidget进行绘制。

想要得到更多关于这种嵌入是如何工作的详细信息,可以查看How Chromium displays web pages design document

共享绘制器进程

通常,每个新的window或标签页是在一个新进程里打开的。浏览器会生成一个新的进程,然后指导它去创建一个RenderView

有时候,有这样一种必要或欲望在标签页或窗口间共享渲染进程。一个web应用程序会在期望同步交流时,打开一个新的窗口,比如,在javascript里使用window.open。这种情况下,当我们创建一个新的window或标签页时,我们需要重用打开这个window的进程。我们也有一些策略来把新的标签页分配的已有的进程(如果总的进程数太大的话,或者如果用户已经为这个域名打开了一个进程)。这些策略在Process Models里也有阐述。

检测crash或者失误的渲染

每个到浏览器进程的IPC连接会观察进程句柄。如果这些句柄是signaled(有信号的),那么渲染进程已经挂了,标签页会得到一个通知。从这时开始,我们会展示一个“sad tab”画面来通知用户渲染器已经挂掉了。这个页面可以按刷新按钮或者通过打开一个新的导航来重新加载。这时,我们会注意到没有对应的进程,然后创建一个新的。

渲染器中的沙箱

给定的WebKit是运行在独立的进程中的,所以我们有机会限制它对系统资源的访问。例如,我们可以确保渲染器唯一的网络权限是通过它的父浏览器进程实现。相似的,我们可以限制它对文件系统的访问权限来使用host操作系统内置的权限。

除了限制渲染器对文件系统和网络的访问权限,我们也可以限制它对用户的显示器以及相关的东西的一些权限。我们在独立的windows桌面(对用户不可见)中运行每个进程。这避免了让渲染器在新的标签页或捕捉按键之间妥协。

归还内存

让渲染器运行在独立的进程中,赋予隐藏的标签页更低的优先级会更加直接。通常,Windows平台上的最小化的进程会把它们的内存自动房东一个“可用内存”池里。在低内存的情况下,Windows会在交换这部分内存到更高优先级内存前,把它们交换到磁盘,以保证用户可见的程序更易响应。我们可以对隐藏的标签页使用相同的策略。当渲染器进程没有顶层标签页时,我们可以释放进程的“工作集”空间,作为一个给系统的信号,让它如果必要的话,优先把这些内存交换到磁盘。因为我们发现,当用户在两个标签页间切换时,减少工作集大小也会减少标签页切换性能,所以我们是逐渐释放这部分内存的。这意味着如果用户切换回最近使用的标签页,这个标签页的内存比最近较少访问的标签页更可能被换入。有着足够内存的用户运行他们所有的程序时根本不会注意到这个进程:事实上Windows只会在需要的时候重新声明这块数据,所以在有充分内存时,不会有性能瓶颈。

这能帮助我们在低内存的情况下得到最佳的内存轨迹。几乎不被使用的后台标签页相关的内存可以被完全交换掉,前台标签页的数据可以被完全加载进内存。相反的,一个单进程浏览器会在它的内存里随机分配所有标签页的数据,并且不可能如此清晰地隔离已使用的和未使用的数据,导致了内存和性能上的浪费。

插件

Firefox风格的NPAPI插件运行在他们自己的进程里,与渲染器隔离。这会在Plugin Architecture中描述。

如何添加新特性(不用扩充RenderView/RenderViewHost/WebContents)

问题

过去,新的特性(比如,自动填充选取样例)可以通过把新特性的代码导入到RenderView类(在渲染器进程里)和RenderViewHost类(在浏览器进程里)。如果一个新的特性是在浏览器进程的IO线程里处理的,那么它的IPC信息由BrowserMessageFilter调度。RenderViewHost会只为了调用WebContent对象进程调用IPC信息,这会调用另一块代码。所有的浏览器与渲染器之间的IPC信息会被声明在一个巨大的render_messages_internal.h里,为每个新特性修改所有的这些文件意味着这些类会变得臃肿。

解决方案

我们增加了helper类和对上面的每个线程IPC信息的过滤的机制。这使得编写自洽的特性更加容易。

渲染器端

如果你想要过滤和发送IPC信息,实现RenderViewObserver接口(content/renderer/render_view_observer.h)。RenderViewObserver基类持有一个RenderView类,管理对象的生命周期,使其绑定到RenderView(它是可重写的)。这个类就可以过滤和发送IPC消息,此外还可以获得许多特性需要的关于页面加载与关闭的通知。作为一个例子,可以查看ChromeExtensionHelper (chrome/renderer/extensions/chrome_extension_helper.h)。

如果你的特性有一部分代码是在WebKit内的,避免通过WebViewClient接口回调,这样我们就不会使得WebViewClient变得庞大。考虑创建新的WebKit接口给WebKit代码调用,让渲染器端的类去实现它。作为一个例子,查看WebAutoFillClient (WebKit/chromium/public/WebAutoFillClient.h).

浏览器UI线程

WebContentsObserver (content/public/browser/web_contents_observer.h)接口允许UI线程的对象过滤IPC信息,以及给出关于页面导航的通知。作为一个例子:查看TabHelper (chrome/browser/extensions/tab_helper.h)。

浏览器其他线程

为了过滤和发送IPC信息给其他的浏览器线程,比如IO/FILE/WEBKIT等等,实现BrowserMessageFilter接口(content/browser/browser_message_filter.h)。BrowserRenderProcessHost对象在它的CreateMessageFilters函数里创造和增加过滤器。

通常,如果一个特性有许多IPC消息,这些消息应该移动到一个独立的文件(例如,不要加到render_messages_internal.h里)。这对过滤线程(除了IO线程)也有帮助。作为一个例子,查看content/common/pepper_file_messages.h。这允许他们的过滤器PepperFileMessageFilter方便的发送文件到file线程,而不用在很多位置指定它们的ID。

void PepperFileMessageFilter::OverrideThreadForMessage(
    const IPC::Message& message,
    BrowserThread::ID* thread) {
  if (IPC_MESSAGE_CLASS(message) == PepperFileMsgStart)
    *thread = BrowserThread::FILE;
}
时间: 2024-08-28 15:03:27

【译】Chromium多进程架构的相关文章

Chromium多进程架构简要介绍和学习计划

Chromium以多进程架构著称,它主要包含四类进程,分别是Browser进程.Render进程.GPU进程和Plugin进程.之所以要将Render进程.GPU进程和Plugin进程独立出来,是为了解决它们的不稳定性问题.也就是说,Render进程.GPU进程和Plugin进程由于不稳定而引发的Crash不会导致整个浏览器崩溃.本文就对Chromium的多进程架构进行简要介绍,以及制定学习计划. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 一个Chr

Chromium多进程资源加载

webkit笔记,主要来自 朱永盛 <WebKit技术内幕> 学习笔记,转载就注明原著,该书是国内仅有的Webkit内核的书籍,学习的好导师,推荐有兴趣的朋友可以购买 多进程 资源的实际加载在各个WebKit Port中有不同的实现.Chromium采用的是多进程的资源加载机制 根据带有资源缓存机制的资源加载过程,在ResourceHandle类之下的部分,是不同的移植对获取资源的不同实现. 在Chromium中,获取资源的方式是利用多进程的资源加载架构.如下图,描述了 关于 Chromium

Chromium多进程机制解析

关于Chromium IPC多进程分析的文章很多了,这篇尝试以浅显的方式解释Chromium多进程机制,解析IPC内部运作的基本机制. Chromium如何保证多进程的性能 对于一个多进程应用,其核心要解决的是并发的问题.因为底层IPC机制的原因,其中一条路径又进一步演变为并发网络通信问题,两个面: 线程/进程 和 网络. 在Chromium中, 主要运用了以下关键技术: Unix Domain Socket (POSIX下使用的IPC机制) libevent (轻型事件驱动的网络库,用于监听I

Chrome设计文档-多进程架构

chromium multi-process architecture 本文档从high-level的角度描述Chromium的多进程架构. 问题 要构建一个决不崩溃或挂起的渲染引擎几乎是不可能的.同样的,要构建一个100%安全的渲染引擎也是不可能的. 从某些角度来看,当今的web浏览器有点类似于过去的单用户,多任务操作系统.正如一个异常的程序会导致整个系统down掉,一个异常的网页也会导致一个现代浏览器挂掉. 现代操作系统之所以更加健壮利益于它们把应用放到隔离的进程中.一个应用的崩溃不会影响其

[转载]为什么浏览器会使用多进程架构

http://blog.csdn.net/ithzhang/article/details/7917754 在使用浏览器时偶然发现虽然仅仅打开一个标签页,但是在任务管理器内发现有多个浏览器进程在运行,占用了不小的内存,当时很纳闷:为什么一个浏览器却需要多个进程呢?不经意间在网上发现这篇文章,以Google chrome浏览器为例,讲解了使用多进程构架的浏览器.翻译给大家,希望对有英语阅读困难的同学有所帮助,第一次翻译技术文章,好多术语不明白啥意思,也没有搜到都是凭理解翻译的.如cross-sit

[转载]详解主流浏览器多进程架构:Chrome、IE

http://www.cnbeta.com/articles/109595.htm 随着Web浏览器重要性的日益突出,恶意软件.木马.间谍软件等网络攻击也呈现逐渐的上升.而面对 如此众多的潜在威胁,为了确保用户的安全性和稳定性,浏览器不得不改进浏览器的性能,其中之一就是向用户提供多进程浏览.在浏览器中添加多进程浏览功能之 后,即使是浏览器其中的一个进程出现了崩溃现象,其他的进程也不会受到影响.例如,如果一个网站中有漏洞或包含恶意代码,它就有可能摧毁当前运行在这个网 站上的标签,但是它却不会影响其

Nodejs学习之多进程架构

操作系统的资源是有限的,这通常意味者操作系统分配给进程或线程的资源是有限的,在多核cpu普及的时代,如果只使用单核(常说node是单线程的),则无法充分压榨硬件性能,今天和大家介绍的就是nodejs多进程架构,希望可以帮助大家更好的学习nodejs ,一起来看看吧.  模块介绍  node提供了child_process模块,该模块提供4个方法  1.spawn() 启动一子进程来执行命令  2.exec() 启动一子进程来执行命令,与spawn()不同的是提供一个回调函数获知子进程的状况  3

[译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)

原文:[译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口) 应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等.接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的.与之前的UI相比,这次我们加上一个"Cal Tax"按钮,当我们点击这个依赖于“sales amount”的按钮时,它会计算税费并显示在同窗口内. 为了完成所述的功能,我们先在Model类中添加一个

游戏服务器之多进程架构通信 协程切换只是简单地改变执行函数栈,不涉及内核态与用户态转化,也涉及上下文切换,

游戏服务器之多进程架构通信 https://gameinstitute.qq.com/community/detail/124098 https://www.zhihu.com/question/23508968 游戏服务器与普通服务器有什么区别? 游戏开发中的TCP.UDP.HTTP.WebSocket四种网络通讯协议对比 https://gameinstitute.qq.com/community/detail/127562 https://www.jianshu.com/p/4eb37c1