Chromium多进程架构(1)

浏览器结构模型

Chromium主要有Browser,Render,GPU等进程,还有插件进程没在下图表示。由于Chromium工程设计的灵活性,提供多种选择,所以这几个可以部分为独立进程,也可以不设置为独立进程。当然这种灵活性本身也增加了不少工程量。

Chroimium 跨进程模型

1、 Browser进程

页面显示,tab页面管理,用户交互,下载管理等。

2、Render进程

渲染进程,根据不同情况可以为一个或者多个,

  • Processpersiteinstance:每一个页面都创建一个独立的Render进程,不管这些页面是否来自于同一域。
  • Processpersite:属于同一个域的页面共享同一个进程,而不同属一个域的页面则分属不同的进程。
  • Processpertab:Chromium每个标签页都是独立进程
  • Singleprocess:该类型的含义是,Chromium不单独为页面创建任何独立进程,所有渲染工作都在Browser进程中进行,它们是Browser进程中的多个线程。

3、GPU进程

4、NPAPI插件进程

>>>不同平台之间的跨平台问题

Chromium由Google开源维护,代码规模异常庞大,跨多个平台,包括Mac 系统,Linux系统,Windows系统,iOS系统(其中有部分和mac cocoa共用)以及Google自己的Android系统。Chomium维护了多个平台和UI的一致性,这也是导致他异常复杂的原因之一了。
我们可以参考一下Chromium跨平台的一些做法,这些做法让代码结构易于维护和保持一致性。

一、就是利用后缀命名的方式:

Mac文件用_mac ,其中 涉及UI(cocoa)部分用_cocoa。 Mac Cocoa: chrome/browser/ui/cocoa
Linux文件用_linux后缀,其中GTK专有的部分用_gtk, 其他专有部分用_x。Linux GTK: chrome/browser/ui/gtk
Windows系统用 _win后缀。
iOS用_ios后缀,不过iOS部分使用_mac。
各平台(Mac iOS Linux)用_posix 后缀share文件。
浏览器前端代码分别由各自的平台自己的目录下面。

二、 #ifdef大法

ref C++语言。 待续C++部分

三、impl大法

ref C++语言。头文件h文件中,可以用#ifdef区别不太的平台,如果比较大的实现部分可以用implenataion的方式来分离。
在base目录下就有不少的例子, 其中waitable_event.h 中,基于不同平台的情况定义通用API。其中给不同的平台定义了不同的实现,当然,如果需要定义一些通用的东西还是需要增加waitable_event.cc的实现的。

和waitable_event有关的目录

另外,单独的几乎没有共用部分的代码可以使用xx_xx_win这样的方式来命名,其中的类Xx_Xx_Win。

浏览器的启动过程代码

浏览器启动部分代码目录:


启动入口目录.png

Windows

在Windows系统上,构建一个dll 来启动WinMain 入口。。。。

Mac

在Mac上打包成一个Framework以及一个可执行文件,这二者可链接在一起。通过main函数启动ChromeMain来启动。 另外还有一个启动入口位于/src/chrome/app_shim/chrome_main_app_mode_mac.mm。这个入口同样调用ChromeMain函数

Linux

由于沙盒的因素,可以启动一个子进程,确保子进程本身不会再进main函数。 最后也同样是调用ChromeMain函数。


渲染模型

Chromium及其庞大复杂,其中webkit/blink 渲染页面主要包括如下几个步骤:

  • 1、解析成DOM
    ---- 每一个HTML节点都可以对应到DOM树种的一个节点Node。 其中顶层根节点应该就是Document节点。

  • 将DOM转成RenderObject树
    ----- DOM树种的每个可视节点都对应到Render树的每个节点,并且通过GraphicsContext绘制。GraphicsContext可以wrap一些skia opengl等,关于 GraphicsContext待续。

  • 转成RenderLayer
    ---- 每一个RenderObject节点都可以通过祖先节点直接或者间接的对应到RenderLayer节点。有共同坐标系空间的RenderObject都在一个RenderLayer。
    符合一些条件可以为部分的RenderObeject创建一个RenderLayer, 定义 RenderBoxModelObject::requiresLayer()
    DOM树的Document节点对应的RenderView节点。DOM树中的Document的子女节点,也就是HTML节点对应的RenderBlock节点。显式的指定CSS位置的RenderObject节点。有透明效果的RenderObject节点。节点有溢出(Overflow)、alpha或者反射等效果的RenderObject节点。使用Canvas2D和3D(WebGL)技术的RenderObject节点。Video节点对应的RenderObject节点。
*   页面的根节点
*   显示的有CSS指定的位置属性(相对 绝对 or转换)。
*   透明节点
*   有溢出 alpha或者反射效果的节点
*   有一个CSS过滤器
*   可以有3D (WebGL) 或者加速2D Context 对应到<canvas> 节点
*   对应到 <video> 节点

所以RenderObject和RenderLayer不是一一对应的关系。并且RenderLayer本身也是树形结构。


  • 从 RenderLayers 到 GraphicsLayers**
    为了利用Compositor,部分RenderLayer有自己的BackingSurface。所有的RenderLayer都有都使用自己的graphicLayer 或者自己最近祖先的GraphicLayer。 这点和RenderObject 和 RenderLayer关系类似。
    每个GraphicsLayer都有一个GraphicsContext供关联的RenderLayers绘制。 合成器最终负责在随后的合成过程中将GraphicsContexts的位图输出一起合并到最终的屏幕图像中。
    从理论上讲,每个单独的RenderLayer都可以将其自身绘制到单独的支持表面上,但实际上在内存方面(尤其是VRAM)这可能非常浪费。 在当前的Blink实现中,必须满足以下条件之一才能使RenderLayer获得其自己的合成层(/third_party/blink/renderer/platform/graphics/compositing_reasons.h):
*  <video>元素使用加速视频解码来使用图层
* 图层由具有3D上下文或加速2D上下文的<canvas>元素使用
* 图层用于复合插件
* 图层使用CSS动画以提高其不透明度,或使用动画的Webkit转换
* 图层使用加速的CSS过滤器
* 层具有作为合成层的后代
* 图层的z索引较低的同级对象具有复合层(换句话说,该层与复合层重叠,应在其顶部进行渲染)

使用GraphicLayer合成消耗内存和其他资源方面会比较昂贵。

  • 从GraphicsLayers 到 WebLayers 再到 CC Layers
    在我们开始使用Chrome的合成器实现之前,只需要再进行几层抽象即可! GraphicsLayers可以通过一个或多个Web * Layers表示其内容。 这些是WebKit端口需要实现的接口。 有关诸如WebContentsLayer.h或WebScrollbarLayer.h之类的界面,请参见Blink的public / platform目录。 Chrome的实现位于src / blink /renderer/compositor_bindings中,使用Chrome合成器层类型实现Web*Layer抽象接口。

以上各部分转换图的大致关系如图:


DOM Tree 、 RenderObject Tree 、 LayerTree 、Graphic Layer对应关系

//> * 将绘制纹理 栅格化给GPU process

Render渲染页面涉及到的流程以及重要类示意图:

render process的主要内容

硬件加速 加速合成模型

Chromium合成器设计用于管理GraphicsLayer树结构以及其frame生命周期的协调关系的软件lib。目录位于src/cc 目录。
render过程分两步:
1 首先是paint。
2 然后是合成。
compsitor在合成之前会对每个层做必要的转换(CSS指定其转换属性)。所以,由于paint和compositor分离,任意一层的无效仅仅需要重绘该层即可。

  • 特别需要注意区分的概念
  • draw指的是一个compositor,其可以最终将合成层绘制到屏幕上。
  • paint 其实是layer的支持,在CPU做软件光栅化的位图(bitmaps with software rasterization),GPU则是硬件光栅化的纹理(textures in hardware rasterization)。

回顾一下软件绘制的模型

Renderer进程(通过IPC和共享内存share memory)将有页面内容的bitmap传递到Browser进程进行显示。
在此绘制方法中,通过从后到前顺序绘制所有RenderLayers来呈现页面。从根开始递归遍历RenderLayer,大部分工作在RenderLayer::paintLayer中执行,有以下基本步骤:

  • 确定该层是否与损伤rect相交以尽早取出。
  • 通过调用negZOrderList中的图层的paintLayer()来递归地绘制此图层之下的图层。
  • 要求与此RenderLayer关联的RenderObject进行绘制。
  • 这是通过从创建该图层的RenderObject开始递归RenderObject树来完成的。只要找到与其他 RenderLayer关联的RenderObject,遍历就会停止。
  • 通过调用posZOrderList中的图层的paintLayer来递归地绘制该图层之上的图层。
  • 在这种模式下,RenderObjects通过向单个共享GraphicsContext中发出绘画调用,将自己绘制到目标位图中。备注 这里GraphicsContext 由skia实现。
CPU渲染架构

一旦所有RenderLayers完成paint到shared bitmap上,该bitmap仍需要将其绘制到屏幕上。在Chrome中,bitmap驻留在share memory中,并通过IPC将其控制权传递给browser process。然后,browser process负责通过操作系统的window API绘制该bitmap。(例如,使用Windows上的相关HWND)

GPU加速渲染的情况

在硬件加速架构中,合成是通过调用特定于平台的3D API(Windows上为D3D;其他任何地方为GL)在GPU上进行的。 渲染器的合成器实质上是使用GPU将页面的矩形区域(即根据图层树的转换层次结构相对于视口定位的所有那些合成层)绘制为单个位图,即最终页面图像。

由于多进程架构沙箱的存在,处于安全因素的考虑,render进程无法访问调用系统的3D绘制功能API(GL / D3D)的调用。故,GPU渲染架构中,额外增加了一个GPU进程。这种方式通过client-server方式来协调工作。
Client端(render进程or Native Cient)将指令序列化发给共享内存share memory的环形缓冲区ring buffer中(ring buff的数据结构待续),Server端(也就是GPU进程,此进程可以访问系统3D绘制API)从ring buffer取出指令来最终绘制。

GPU进程的工作方式

Client端向Shared Memory中的command (ring buffer)发送命令,Server取出命令,二者可以异步完成绘制的协调工作。另外,较大的资源数据(比如纹理等等)通过Shared Memory同步数据。
另外,也可以通过mailbox的方式来在不同的命令buffer中沟通以及管理好他们的生命周期。
Sync points也可以通过mailbox来完成command buffer之间的非阻塞同步。

GPU 多通道模型,以及其他细节问题待续。

其他问题

IPC的mojo文件,基础数据结构 异步的问题,渲染opengl skia问题
事件体系 网络优化 安全性 以及IDL编译打包的问题等等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容