这篇研究两个问题:chromium对线程的封装和进程通信。主要参考chromium的官方技术文档:TreadingInter-process Communication (IPC)

chrome速度快的优点,主要得益于线程模型的设计,这也是chrome最值得研究的技术点。

 
    一、线程模型
 
    chromium中的线程分为很多种类型,每个线程中有一个MessageLoop处理线程消息,对应实现:
    Thread - base/threading/thread.h
    MessageLoop - base/message_loop.h

    线程的类型包括:io_thread,file_thread,db_thread,safe_browsing_thread等,其中io_thread是一个事件分发线程,管理browser进程和子进程的通信。(上一篇多进程架构图中可以看到它。)
 
    chromium线程设计有一个非常重要的目标:保证UI线程的快速响应,也就是要确保UI线程中没有阻塞的I/O或耗时操作。保证这一点需要一个高效的多线程模型,面临的问题是:
    1、想尽一切办法减少多线程锁;
    2、多线程通信方式。
 
    chromium的实现手段:
    1、线程内消息循环的设计,为线程异步调用打下基础;
    2、Task封装,解决了加锁的问题,同时用command模式统一同步和异步调用。
    也就是说,Task是对一个任务处理的封装,而线程的消息循环都认识Task,这样整个多线程框架其实就是Task的传递和执行的过程,并且锁只在传递Task时发生。多么简单有效的模型!
 
    消息循环
    来看张图(引用自Chrome源码剖析
    

图示将线程的消息循环处理描述的非常清楚,基本思路和windows的消息循环非常相似。

当然,不同类型的线程并不会处理所有的事件,但所有的消息循环都会处理Task。

    线程消息循环分为MessageLoop和MessagePump,其中MessageLoop专门处理Task,而MessagePump处理其他消息,
 
发现Task时交给MessageLoop。不同线程的消息循环的MessageLoop和MessagePump如图:
 

    Task    
    Task是对行为的封装,或者说是将处理函数封装为一个对象。Task对象有一个Run函数,供目标线程的消息循环调用,执行Task的处理。还是看张图:

    如果A线程想让B线程处理一个事务,A只需创建一个Task,将事务处理代码封装好,找到B线程的MessageLoop对象,调用PostTask方法将Task插入消息队列。PostTask将立即返回,A线程继续处理自己的消息循环。B线程消息循环处理到Task时,调用其Run方法完成事务处理。
    chromium对Task的创建和传递做了封装,并定义了丰富的Task类型,满足多种场景需要。同时支持Task自身的日志和统计,便于调试。
    参考文章:
    
    二、进程通信(IPC)
 
    chromium的进程通信在Windows下采用命名管道(在Linux & Mac上采用socketpair),涉及到的进程主要是Browser process、Renderer process和Plugin process。
 
(具体可以参考我的上一篇博文。)实际上最主要的通信发生在Browser和Renderer之间,基本上每一个Renderer process对应一个named pipe与Browser通信。
 
管道通信采用异步模式,保证不会发生阻塞。
 
    根据上一篇博文提到的多进程模型图,可以知道Browser process中有一个I/O线程专门处理IPC,I/O线程和main thread之间通过ChannelProxy传递消息,I/O线程的主要目的是为了处理请求resource等可能阻塞的动作。Renderer process则用其main thread处理进程消息收发。
 
    命名管道根据定义好的规则生成,需要通信的两个进程都认识这个管道,之后就可以按照管道的技术特点通信了。
 
chromium将这些逻辑用IPC::Channel封装,Channel处理三件事情:Send,Listen,处理Watcher,看张图:

    
 
    发送进程调用Channel::Send将消息放到自己某线程的消息队列中,消息循环发现消息的信号量激活则序列化消息写到管道中。
 
操作系统负责将管道内容进行传递并通知接收进程,接收进程有一个I/O类型的线程,其消息循环处理Watcher(参考前面的讲解),
 
当发现Watcher的信号量被激活(收到消息),调用Watcher中对应的OnObjectSignaled方法,该方法通知本进程的Channel去管道中读取数据,并调用Listener解析处理。
 
    chromium用消息循环支撑了进程通信机制,并保证了异步处理防止阻塞。
 
    上面提到的ChannelProxy与Channel是什么关系呢?chromium为了保证线程安全,将Channel设计为由每个进程的I/O线程处理。
 
如果进程中的非I/O线程想发送进程消息怎么办?一个简单思路是将消息发送封装成Task交给I/O线程去处理,chromium将这个处理封装成了ChannelProxy,方便使用。
 
ChannelProxy甚至支持接收到消息后将其返回给原始发送消息的线程。基于以上,Browser的main thread想发送进程消息都必须通过ChannelProxy让I/O thread处理。
    有时需要同步的进程通信,这部分封装在ChannelProxy的子类SyncChannel中。
 
    chromium中的消息有两类:Routed消息和Control消息。简单来说,Routed消息有明确去向,会关联到一个视图上;
 
Control消息不指定到视图,通常被创建管道的class处理。
    chromium为消息和Channel的使用封装了一套宏和模板,来简化进程通信的调用。具体可以参考:Inter-process Communication (IPC)

chromium ②的更多相关文章

  1. QT5利用chromium内核与HTML页面交互

    在QT5.4之前,做QT开发浏览器只能选择QWebkit,但是有过使用的都会发现,这个webkit不是出奇的慢,简直是慢的令人发指,Release模式下还行,debug下你就无语了,但是webkit毕 ...

  2. Google之Chromium浏览器源码学习——base公共通用库(一)

    Google的优秀C++开源项目繁多,其中的Chromium浏览器项目可以说是很具有代表性的,此外还包括其第三开发开源库或是自己的优秀开源库,可以根据需要抽取自己感兴趣的部分.在研究.学习该项目前的时 ...

  3. 如何在windows上编译Chromium (CEF3) 并加入MP3支持(二)

    时隔一年,再次编译cef3,独一无二的目的仍为加入mp3支持.新版本的编译环境和注意事项都已经发生了变化,于是再记录一下. 一.编译版本 cef版本号格式为X.YYYY.A.gHHHHHHH X为主版 ...

  4. 如何在Windows上从源码编译Chromium (CEF3) 加入mp3支持

    一.什么是CEF CEF即Chromium Embeded Framework,由谷歌的开源浏览器项目Chromium扩展而来,可方便地嵌入其它程序中以得到浏览器功能. CEF包括CEF1和CEF3两 ...

  5. 构建基于Chromium的应用程序

    chromium是google chrome浏览器所采用的内核,最开始由苹果的webkit发展而出,由于webkit在发展上存在分歧,而google希望在开发上有更大的自由度,2013年google决 ...

  6. ubuntu中chromium无法播放flash,安装flash

    ubuntu14.0.4中系统自带的chromium无法播放flash,后来查了下,得知chromium已经不支持adobe flash了,用户可使用pepper flash替代.安装pepper f ...

  7. windows下编译chromium浏览器的15个流程整理

    编译chromium 系统为windows, 国内在windows上编译chromium的资料比较少, 我这篇文章只能作为参考, 记录我遇到的一些问题,因为chromium团队也会修改了代码,或者编译 ...

  8. Google之Chromium浏览器源码学习——base公共通用库(二)

    上次提到Chromium浏览器中base公共通用库中的内存分配器allocator,其中用到了三方库tcmalloc.jemalloc:对于这两个内存分配器,个人建议,对于内存,最好是自己维护内存池: ...

  9. 浏览器-10 Chromium 移动版

    移动版 chromium 的iOS版和Android是为两个流行的移动操作系统设计的, UI方面进行了 较大的重新设计; 两者从外观上看颇为相似,但是其内部的渲染引擎的差别非常的大,原因在于iOS对应 ...

  10. 浏览器-09 javascript引擎和Chromium网络栈

    语言的运行 C/C++语言 使用编译器直接将它们编译成本地代码(机器指令),这是由开发人员在代码编写完成之后实施; 用户只是使用这些编译好的本地代码,这些本地代码被系统的加载器加载执行,由操作系统调度 ...

随机推荐

  1. 邂逅明下 HDU - 2897

    Problem description: 有三个数字n,p,q,表示一堆硬币一共有n枚,从这个硬币堆里取硬币,一次最少取p枚,最多q枚,如果剩下少于p枚就要一次取完.两人轮流取,直到堆里的硬币取完,最 ...

  2. CentOS7.3环境下源码安装httpd

    CentOS7.3环境下源码安装httpd 本文在CentOS7.3下,源码安装apache服务httpd2.4. 1.下载好源码安装包 [root@localhost ~]#ll total 625 ...

  3. 2018"百度之星"程序设计大赛 - 资格赛 A/B/E/F

    调查问卷  Accepts: 505  Submissions: 2436  Time Limit: 6500/6000 MS (Java/Others)  Memory Limit: 262144/ ...

  4. PAT 1005 Spell It Right

    1005 Spell It Right (20 分)   Given a non-negative integer N, your task is to compute the sum of all ...

  5. WDA基础十四:ALV字段属性配置表

    ALV配置表管理 一.字段属性配置表 对于可编辑的ALV不用这个,尽可能多的设置一些控制: 单元格类型:默认A,特殊选择 ZLYE_TYPE        E       A       1      ...

  6. CSS知识点(一)

    一.引入CSS样式(重点掌握) 行内样式 内接样式 外接样式 3.1 链接式 3.1 导入式 css介绍 现在的互联网前端分三层: HTML:超文本标记语言.从语义的角度描述页面结构. CSS:层叠样 ...

  7. FJUT16级第一周寒假作业题解G题

    题目链接:http://210.34.193.66:8080/vj/Contest.jsp?cid=160#P6 涨姿势题1 TimeLimit:1000MS  MemoryLimit:128000K ...

  8. Redis php常用操作

    $redis = new redis(); //连接 $redis->connect('127.0.0.1',6379); // //设置值 $result = $redis->set(' ...

  9. [LeetCode] 113. Path Sum II ☆☆☆(二叉树所有路径和等于给定的数)

    LeetCode 二叉树路径问题 Path SUM(①②③)总结 Path Sum II leetcode java 描述 Given a binary tree and a sum, find al ...

  10. 禁止网站被别人通过iframe引用

    https://blog.csdn.net/dugujiancheng/article/details/51669164 解决方案一:js方法这种方法不可靠,不推荐使用 <script type ...