webkit 架构和模块 及chromium的多进程和多线程模型

728 阅读7分钟

此内容是笔者关于webkit技术内幕的学习记录(ps包括笔者自身的认知理解),有错误的地方望理解和指出,笔者定会及时更正。学习的路上,一起互助前行。
todo:有待继续补充替换。

  1. webkit架构和模块 (由基础到应用)

1)操作系统:包括2D/3D图形库,网络库,存储,音视频库,...提供底层服务
2)webkit层:包括webCore,jsCore,webkit Ports(对操作系统提供基础服务的封装的接口调用),合成器,等
2.1) webCore:对html解析-->构建dom,对css的解析-->构建cssOM。到构建render Object tree--->layout--->render layout tree.以及对svg,canvas等的解析。
2.2)jsCore:提供对js的解释和解析。

3)webkit 接口层:提供对webkit功能的绑定和对应接口输出。

了解了webkit的简单分层,再来看下chromium的结构实现。 架构层次清晰,模块功能越单一,灵活性越强,可拓展性越强。

  1. chromium的模块架构 从下到上。
    2.1) 基础服务模块: blink(webkit),v8(处理js的模块),GPU,UI,... (主要是html,css,js的解析,渲染和绘制的基础模块)
    2.2)content 模块和 content 接口 content 模块和 content 接口的目的是隐藏基础服务逻辑功能,提供简单的接口调用。
    2.3)chromiun等浏览器客户端程序 更合理和有效的组织接口调用,提供从url到页面展示的功能。

那引出下一个问题,怎么更合理和有效的组织呢?
目前最有效的方式是多进程,多线程架构模型。
目的都是为了安全和高效快速。

  1. chromium的多进程架构模型
    基础进程有:
    3.1) browser进程: 浏览器的主进程,负责浏览器界面的展示,以及浏览器页面的管理(和绘制),负责其他进程的创建和销毁。以及浏览器的TAB的前进、后退、地址栏、书签栏的工作和处理浏览器的一些不可见的底层操作,比如网络请求和文件访问后面涉及缓存资源的管理等。 有且仅有一个。
    主要线程:
    UI线程:负责处理用户事件,以及绘制从render进程接收到的数据。 IO线程:负责传递数据or任务。

    3.2)render进程: 渲染进程,主要负责页面的渲染,webkit的渲染工作主要在这个进程完成。render进程的数量并不一定与浏览器对应打开的页面一样,会更多,有能有内嵌的iframe,可能有webworker进程事件导致。
    主要线程:
    a. GUI渲染线程:负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。
    b. js线程:负责处理 Javascript 脚本程序。(例如 V8 引擎)
    c. 事件触发线程:归属于浏览器而不是 JS 引擎,用来控制事件循环;
    d. IO线程:
    e.定时触发器线程:setInterval 与 setTimeout事件
    f.异步http请求线程

     > 浏览器的event loop ?
     感兴趣的可以自行了解。
    

    3.3)GPU进程:主要用于图像加速,当前仅当GPU硬件加速开启的时候才会被创建,最多只有一个。

    ***这么引出一个问题,什么是硬件加速?怎么开启GPU硬件加速?
    1)什么是硬件加速? 硬件加速是利用GPU的硬件计算能力,帮助渲染页面,提升渲染速度。 但硬件加速有也一定局限。通常不像软件渲染那样只是计算其中更新的区域,对于GPU绘图而言,一旦有更新请求,如果没有分层,引擎可能需要重新绘制所有的区域,因为计算更新部分区域对GPU来说可能更加耗费时间。当有了分层,部分区域更新可能只是页面的一层或者几层,对于GPU就只需要绘制这几个层,然后再合并之前的层就可以,不需要整个页面重新绘制。这样既使用了GPU的计算能力,又能够减少重绘的开销。
    todo: 更具体的后面再叙述;
    2)怎么开启GPU硬件加速?RenderLayer树中哪些对象可以是合成层?
    a. 具有CSS 3D属性或者CSS 透视效果。( translate3d,translateZ,perspective ) b. 特殊Html5元素,如video, c. 使用canvas或者WebGL技术的元素 d. 使用css Filter技术 e. 使用了剪裁Clip或者反射(Reflection)属性,并且它的后代中包括一个合成层。 f. 有一个Z坐标比自己小的兄弟节点,并且该节点是一个合成层。

    说到这里,display,visibility,opacity? 通常:display会引起回流和重绘,visibility会重绘。opacity所在元素不在合成层中的化,opacity改变,它及其子元素会重绘制。如果在合成层上,只会composite。

    3.4)合成器进程: 3.5)其他...

    对进程模型的优点很明显:多进程调用,充分发挥多核cpu效率;browser进程和render进程分开,避免render进程崩溃影响这个浏览器;不同render进程分开,互不影响,也保证了安全(不同进程间不能随意获取内存数据);等等。 不过也有不好的一面,也就是进程间的通信的复杂度和消耗也要加大。

    这么引出一个问题,进程间通信的方法?(进程间的数据交换) 进程通信的三大方式:
    a. 共享存储 : 操作系统单独分配一块内存空间,提供给进程共享;
    两个进程对于共享空间的访问是互斥的,互斥的控制用操作系统控制。 1)基于数据结构的共享:(只能存放特定单一的数据结构,低级通信) 2)基于存储区的共享 (最快的IPC方式)(重点):一‘大块’区域,用进程自主控制数据形式。
    b. **消息传递:
    指进程间的数据交换以格式化的消息为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
    消息Message分:
    消息头(发送进程ID,接收进程ID,信息类型,消息长度等格式化信息) 消息体:具体交换信息。
    消息传递可分为: 1) 直接通信:消息直接挂到接收进程的消息缓存队列上。 2)间接通信:消息要先发送到中间实体(信箱)中,因此也称“信箱通信”。比如:电子邮件系统
    c. 管道通信:
    ‘管道’指用于读写进程的一个共享文件,又称pipe文件,也就是在内存中开辟的一个固定大小的缓冲区。通过管道通信,也可以理解为是通过读写文件来进行数据交换。
    一个管道只能半双工通信。
    管道访问也是互斥的。

     **通信的特点:  
         数据以字符流的形式被读写。  
         每次写文件时,读文件进程会被阻塞,必须写满时,才允许被读。
         每次读文件时,写文件进程会被阻塞,必须取完文件,管道变空,才允许被写。
         数据一旦从管道读取,就会从管道中抛弃,被抛弃的数据无法找回。
    
     **基于特点,可以理解管道通信更是适用于临时的,频率和数据量较小的,通信负责度低(大多只涉及两方通信)的通信。
    
  2. 多线程模型 学过操作系统,我们都知道,进程是内存分配的最小单位,线程是计算机调度的最小单位。一个进程下可以有好多线程,而chromium设计多线程的目的是为了更高效的调控,保持用户界面的高响应度。
    如何保证用户界面的高响应度呢?
    a.对于browser进程,需要保证UI线程不会其他费时的操作阻碍而影响用户对界面的操作。 b. 对于render进程,保证在执行渲染线程时,不让其他操作阻碍。更甚者,可以利用多核的优势,将渲染过程管线化,这样可以让渲染的不同阶段在不同的线程中。

总结,多于进程和线程的划分,是应该创建一个进程,还是创建线程,也是一个需要权衡的。

------未完待续----