欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > DOC文档下载  

    源码分析.doc

    • 资源ID:4169201       资源大小:2.01MB        全文页数:28页
    • 资源格式: DOC        下载积分:8金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要8金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    源码分析.doc

    chrome为我们提供的一张进程图:一个浏览器的主进程<BrowserProcess>,N个渲染进程<RenderProcess>。主进程中包括了UI线程<MainThread>和资源分派线程<IOThread>,一个渲染进程包括了资源分派线程<IOThread>和主渲染线程<RenderThread>其中浏览器进程和渲染进程之间靠的是通道<Channel>.来进行连接的。 chrome有4种启动方式1:每个TAB一个进程。2:每个域名一个进程。3:每个网页一个进程。4:每个网页以及从这个网页说打开的其他连接一个进程。详细资料参见Multi-process Architecture进程之间通讯-命名管道(Named Pipes )     所谓Named Pipes,其实是一个WINDONWS内核对象,关于内核对象的介绍可以参考WINDOWS核心编程。Named Pipes 在NT以上的系统才被支持。Named Pipes分客户端和服务器端,服务器创建一个命名管道,客户端可以连接到这个管道上。WINDOWS对命名管道的支持非常完善,不当支持本地命名管道,还支持跨网络的命名管道,可以从一台机器上连接到另外一台机器。工作的基本流程是这样的:    服务器和客户端确定命名管道的名称,这个名称是有讲究的,具体怎么给管道取名,同学们可以去网上查看资料。    服务器:调用 CreateNamedPipe 创建一个命名管道,然后调用ConnectNamedPipe等待客户端的连接,采用WriteFile来传送数据,用ReadFile来读数据。    客户端:调用CreateFile来连接 服务器,采用WriteFile来传送数据,用ReadFile来读数据。其实同学们看见 CreteFile,WriteFile,ReadFile,不比担心它们会写磁盘,其实写的是系统的一块缓冲区,所以效率不比担心,最耗效率的地方其实就是系统调用和用户本地调用的切换说花费的时钟周期。     chrome中使用Name Pipes采用了异步的调用的方式,这就是所谓的完成端口模型。这会增加一点理解的复杂度。关于完成端口,我们可以把系统看成服务器,我们的程序是客户端,当需做一个任务,比如服务器调用ConnectNamedPipe,如果先前创建Name Piples设置了FILE_FLAG_OVERLAPPED,那么调用该函数会立即返回,然后系统工作,当有连接到来的时候,系统会激活先前设置的事件,来通知程序。和WINDOWS窗口口号类似:“你别等我,我会通知你的“。 在Chrome中,BrowerProcess和RenderProcess, BrowerProcess和PluginProcess之间是怎么传递的呢?Chrome中有一个叫Channel的对象,这个对象封装了NamePiple,所有的进程间通讯将通过这个对象来完成,也就是说,BrowerProcess和RenderProcess内部都分别拥有一个Channel的对象,用这个对象来实现彼此的互通。那么接下的问题是:这个对象发送的字节流的格式是什么?这就牵出了另外一个对象Message,Message是一个被精心定义的对象,它继承于Pickle, Pickle是个对二进制进行读写操作的类,当然读写操作由它的派生类来定义。Channel有个Send方法,参数就是Message类型。Channel也把消息的接收,处理,连接出错状态委托给IPC:Channel:Listener的接口,由外部类来处理,这里是ServerListener和ClientListener.这样两个进程直接发送数据,然后一堆问随之而来:1:不是说BrowerProcess里面有个IO线程吗,IO线程用来接受RenderProces和网络下载的线程,那么当Render通过IPC把消息发送给IO线程了,IO线程怎么转发消息到BrowerProcess的主线程?2:RenderProces中的IO线程和RenderProces中的主线程各自职责又是什么?他们之间又是怎么通讯的?3:进程间异步和同步是怎么处理的?在什么情况下应用同步,什么情况下应用异步处理?Chrome的线程模型-消息循环的手段。每一个Chrome的线程,入口函数都差不多,都是启动一个消息循环(参见MessagePump类),等待并执行任务。而其中,唯一的差别在于,根据线程处理事务类别的不同,所起的消息循环有所不同。比如处理进程间通信的线程(注意,在Chrome中,这类线程都叫做IO线程,估计是当初设计的时候谁的脑门子拍错了.)启用的是MessagePumpForIO类,处理UI的线程用的是MessagePumpForUI类,一般的线程用到的是MessagePumpDefault类 (只讨论windows, windows, windows.)。不同的消息循环类,主要差异有两个,一是消息循环中需要处理什么样的消息和任务,第二个是循环流程(比如是死循环还是阻塞在某信号量上.)。下图是一个完整版的Chrome消息循环图,包含处理Windows的消息,处理各种Task(Task是什么,稍后揭晓,敬请期 待.),处理各个信号量观察者(Watcher),然后阻塞在某个信号量上等待唤醒。图2 Chrome的消息循环不同的MessagePump类,实现是有所不同的,详见下表:MessagePumpDefaultMessagePumpForIOMessagePumpForUI是否需要处理系统消息否是是是否需要处理Task是是是是否需要处理Watcher否是否是否阻塞在信号量上否是是Task就是一个类,一个包含了 void Run()抽象方法的类(参见Task类.)。一个真实的任务,可以派生Task类,并实现其Run方法。每个MessagePump类中,会有一个 MessagePump:Delegate的类的对象(MessagePump:Delegate的一个实现,请参见MessageLoop 类.),在这个对象中,会维护若干个Task的队列。当你期望,你的一个逻辑在某个线程内执行的时候,你可以派生一个Task,把你的逻辑封装在 Run方法中,然后实例一个对象,调用期望线程中的PostTask方法,将该Task对象放入到其Task队列中去,等待执行。在线程池,UndoRedo等模块的实现中,用的太多了。在Chrome中,线程模型是统一且唯一的,这就相当于有了一套标准,它需要满足在各个线程上执行的几十上百种任务的需求,因此,必须在灵活行和易用性上有良好的表现,这就是设计标准的难度。为了满足这些需求,Chrome在底层库上做了足够的功夫:1. 它提供了一大套的模板封装(参见task.h),可以将Task摆脱继承结构、函数名、函数参数等限制(就是基于模板的伪function实现,想要更深入了解,建议直接看鼻祖Modern C+和它的Loki库.);2. 同时派生出CancelableTask、ReleaseTask、DeleteTask等子类,提供更为良好的默认实现;3. 在消息循环中,按逻辑的不同,将Task又分成即时处理的Task、延时处理的Task、Idle时处理的Task,满足不同场景的需求;4. Task派生自tracked_objects:Tracked,Tracked是为了实现多线程环境下的日志记录、统计等功能,使得Task天生就有良好的可调试性和可统计性;这一套七荤八素的都搭建完,这才算是一个完整的Task模型多线程模型中,我们需要分清楚啥是同步 啥是异步,在同步模式下,一切看上去和单线程没啥区别,但同时也丧失了多线程的优势(沦落成为多线程串行.)。而如果采用异步的模式,那写起来就麻烦多了,你需要注册回调,小心管理对象的生命周期,程序写出来是嗷嗷恶心。在Chrome的多线程模型下,同步和异步的编程模型区别就不复存在了,如果是这 样一个场景:A线程需要B线程做一些事情,然后回到A线程继续做一些事情;在Chrome下你可以这样来做:生成一个Task,放到B线程的队列中,在该 Task的Run方法最后,会生成另一个Task,这个Task会放回到A的线程队列,由A来执行。如此一来,同步异步,天下一统,都是Task传来传 去,想不会,都难了。图4 Chrome的一种异步执行的解决方案1:消息系统的概述(1)消息系统的静态结构这是消息系统的第一个部分,先看看和消息相关的静态类图:伎俩一:handle-body,pimpl, 桥接MessageLoop基本就是MessagePump的一个代理类,扩充了一些MessagePump没有的功能,chrome本意可以能是想让Message来处理所有事务,而这个messgaePump可以做到对调用者透明。但是对于研究chrome代码的CODER来说,了解MessagePump是不可推卸的责任。后面都会详细分析的。MessagePump和MessageLoop采用用了一种handle-body或称pimpl的伎俩,按照牛逼点的叫法叫着桥接,关于此伎俩可以参考四人帮的设计模式。 伎俩二:委托Chrome中已经用烂了改伎俩,基本上所有代码中都能看见此手法。一个类的内部操作委托给外面的一个对象,通过抽象接口。如上面代码所示,MessagePump把  DoWork  DoDelayWork, DoIdelWork通过MessagePump:Deletgate 的接口委托给M essageLoop去处理,这样比较好的解决了代码间的耦合问题。类似伎俩在消息系统这块还有很多:MessagePump:Watcher           对应handle的事件处理MessagePump:Observer          监视Windows消息的处理 MessagePump:Dispatcher         Windows本地消息的分派MessageLoop:DestructionObserver 用来跟踪MessageLoop的稀构这些都是委托的接口,只不过名字不像MessagePump:Deletgate这么张扬而已。把委托的接口类写到类的内部,对于chrome这种写法我是我以前没有考虑过的,是个非常清晰的代码风格,coder一看就能知道这个委托接口是干吗的。 伎俩三:线程本地存储一个线程怎么获取到当前线程的消息循环对象,通过线程本地存储。所谓的线程本地存储就是把一个变量和一个线程相关联.最简单的说是我定义了一个全局的 int n变量,我把n设置为线程本地存储变量,当开启了4个线程,这四个线程都修改了 n这个变量,结果是n对应于每个线程都有一份拷贝,即四个线程四份n的值。Chrome中是把 MessageLoop对象设置为线程本地存储,每个线程获取线程的消息循环很简单,直接通过调用MessageLoop一个静态的current()方法返回当前线程的消息循环。比如在一个线程里面运行一个消息循环1.  MessageLoop:current()->Run();伎俩四:关于chrome 添加任务的方式注意观察MessageLoop中的任务队列,会发现它有四个队列,如下:incoming_queue_              所有任务都是首先添加到该队列中work_queue_                   当前的工作队列delayed_work_queue_            推迟指定时间执行的任务队列deferred_non_nestable_work_queue_不能重入被推迟执行任务队列现在要弄明白每个队列的在MesageLoop中的语意,只有先了解了语意才能知道为什么要这样设计。incoming_queue_ 和 work_queue_  队列的区别?由于添加队列设计到多线程操作,必然需要对其加锁。程序的设计原则是能不用锁打死也不用,现在chrome的MessageLoop需要段的加入消息,循环内部需要不断地处理消息,如果每次添加和取消息都要对队列加锁,那么是比会影响其执行效率。如是,chrome采用了这样的一个措施,采用两个队列:一个用来从外部线程收集任务的队列(incoming_queue),一个是供内部使用的队列(work_queue),并且保证从work_queue队列中取出任务不需要加锁。遵循以下三个原则:1:每次添加一个任务都需要加锁(任务被添加到incoming_queue)2:每次从work_queue队列中取出任务不需要加锁。3:在work_queue为空时需要把incoming_queue队列中的内容取出来,取出的操作需要加锁这样循环的效率可以提高 40-50%。1. void MessageLoop:ReloadWorkQueue() 2.   / We can improve performance of our loading tasks from incoming_queue_ to 3.   / work_queue_ by waiting until the last minute (work_queue_ is empty) to 4.   / load.  That reduces the number of locks-per-task significantly when our 5.   / queues get large. 6.   if (!work_queue_.empty()7.     return;  / Wait till we *really* need to lock and load. 8.9.   / Acquire all we can from the inter-thread queue with one lock acquisition. 10.   11.     AutoLock lock(incoming_queue_lock_);12.     if (incoming_queue_.empty()13.       return;14.     std:swap(incoming_queue_, work_queue_);15.     DCHECK(incoming_queue_.empty();16.   17. (2)消息动态流程和WINDOWS的传统消息机制类似,但是它扩充了WINDOWS的消息循环机制,使得它能够支持事件对象和任务。Chrome 对自己的线程采取一种lazyCreate 的策略,就是每个线程在需要的时候才被创建。线程之间是通过g_browser_process这个全局对对象来获取相应的线程中的消息循环,然后再通过 消息循环中的PostTask 系列的函数来发送任务到相应的线程队列中去。 上一章对chrome进程间通讯做了一个简单的介绍,利用name piples来传递二进制数据,Chrome把name piples封装在一个channel的类中,利用参数Message相互发送消息。    那么现在将要深入BrowerProcess和 RenderProces里面去,揭开里面有多少线程,线程间怎样交互。现在有有一下的问题:    BrowerProcess中有UI显示部分,消息接受部分,HTTP页面下载部分,然后其他一系列读取COOKIE,写文件,读写数据库,等操作是怎么协调?怎么分工的?之间又是怎么交互的?    RenderProces中渲染部分和接收        BrowerProcess消息部分是怎么交互的?    RenderProces是怎么发送消息的到BrowerProcess中的?注意为了方便理解这里先还是先抛开PluginProcess和sanbox不讲。按照上面的问题本章打算分三部分介绍,一:BrowerProcess 中的线程二:RenderProces中的线程三:BrowerProcess和RenderProces线程交互流程。一:BrowerProcess 中的线程     BrowerProcess里面的线程很多,其中最重要的是IO线程和UI线程。除了这两个线程,还有管理数据库读写的DB线程,管理本地文件读写的FILE线程等等。   要研究每个线程首先我们得了解每个线程的职能。UI 线程顾名思义,管理UI以及UI的消息循环,但是IO线程不能太顾名思义了,IO线程主要有两方面的职能,接收进程间消息(包括渲染进程和插件进程的消 息),还有个职能是接收网络消息所有HTTP页面的下载的消息也由这个线程处理转发,不过除了用IO来表示这个线程也想不出来更好的名字了J。可以先参看下 How Chromium Displays Web Pages 上面的介绍,先引用一张上面的图片:                                                (BrowerProcess基本的线程结构)一个页面是怎样被创建的呢?先弄清楚下面几点说明<静态数据概念>:     1:一个BrowerProcess里面保存一个Browser的列表,每个Browser对象代表着一个浏览器窗口。     2:每个Browser对象里面保存一个WebContents列表(这个列表是用了一个TabStripModel的对象来封装),WebContents就是浏览器上面的HTML页面和标签。    3:每个WebContents中包含了一个RenderViewHost对象。这里要多介绍一下WebContents和 RenderViewHost各自的功能:RenderViewHost主要表现的就是一个HTML页面,WebContents不说大家可能也已经猜到 了,它就是管理标签命令和导航命令的(HTML页面以外的消息由它处理)。讲 一些题外话,GOOGLE声明说他们会在将来支持其他程序调用RenderViewHost的功能,这对微软来说是个相当打的挑战,虽然说瘦死的骆驼比马 大,但是GOOGLE会一步步地同食微软的市场,这匹瘦骆驼也无力于健壮的马来竞争,IE只是他们计划中的一个小计划,闲话不多扯了,杀回来继续。     4:每个RenderViewHost被创建的时候它会创建一个RenderProcessHost的对象,并且创建一个Rander进程,RenderProcessHost的对象会等待Rander进程的连接消息。     5:一个RenderProcessHost对象会创建一个ChannelProxy的代理对象(这个对象将被分配到IO线程里面去运 行),ChannelProxy对象的职责是转发Render进程的消息和网络消息(HTTP页面下载),并且把需要网络消息转发给Render进程。 RenderProcessHost对象还会创建另外一个过滤消息的对象ResourceMessageFilter的过滤器,该过滤器会被添加到 ChannelProxy中,此处也是采用上面重复提到的委托伎俩,ChannelProxy有个过滤消息的委托接口类,然后把消息交给由外面派生类 (ResourceMessageFilter)来处理,如果处理了那么就不转发消息给UI线程了,如果没处理,那么转发消息。     6:每个ChannelProxy里面会包含一个真正的IPC:Channel对象,如果看过我上一篇文章的同学肯定还记的这个 IPC:Channel,不就是进行进程间通讯的东东吗。Channel会把接受到的消息转发给ChannelProxy,由ChannelProxy 决定该消息路由到什么地方。另外一点就是ChannelProxy会收到本进程的消息(网络消息和UI消息和其他的消息),这些消息会根据情况被转发给 Render进程。   ChannelProxy在IO线程中是怎么把Message转换为Task的呢?    同学们可能很奇怪,Message和Task都都好像在前面见过,但是他们之间有什么关系呢?    Message是从Render进程那儿接受到的消息,TASK是消息循环中执行的一个任务,IO线程需要把Message转换为TASK发送到UI线 程中去执行,Chrome开发人员定义了一套NewRunnableMethod 的方法,用来把Message转换为相应的TASK,参看basetask.h代码。ChannelProxy里面保存了UI的消息循环对象的指针,然 后通过该对象PostTask系列函数来发送消息到UI线程中。     一个对BrowerProcess里面的进程大概介绍就这样完成了,对上面的6点我们还可以总结出 1,2,3是在UI线程环境中运行的,4,5是在IO线程中运行的,6是IO和UI线程之间交互方式。  /=飘逸的分割线=/     下一章将对RenderProces里面的线程做简单的介绍,有了BrowerProcess的介绍这就简单得多了:) 上一章对chrome进程间通讯做了一个简单的介绍,利用name piples来传递二进制数据,Chrome把name piples封装在一个channel的类中,利用参数Message相互发送消息。    那么现在将要深入BrowerProcess和 RenderProces里面去,揭开里面有多少线程,线程间怎样交互。现在有有一下的问题:    BrowerProcess中有UI显示部分,消息接受部分,HTTP页面下载部分,然后其他一系列读取COOKIE,写文件,读写数据库,等操作是怎么协调?怎么分工的?之间又是怎么交互的?    RenderProces中渲染部分和接收        BrowerProcess消息部分是怎么交互的?    RenderProces是怎么发送消息的到BrowerProcess中的?注意为了方便理解这里先还是先抛开PluginProcess和sanbox不讲。按照上面的问题本章打算分三部分介绍,一:BrowerProcess 中的线程二:RenderProces中的线程三:BrowerProcess和RenderProces线程交互流程。一:BrowerProcess 中的线程     BrowerProcess里面的线程很多,其中最重要的是IO线程和UI线程。除了这两个线程,还有管理数据库读写的DB线程,管理本地文件读写的FILE线程等等。   要研究每个线程首先我们得了解每个线程的职能。UI 线程顾名思义,管理UI以及UI的消息循环,但是IO线程不能太顾名思义了,IO线程主要有两方面的职能,接收进程间消息(包括渲染进程和插件进程的消 息),还有个职能是接收网络消息所有HTTP页面的下载的消息也由这个线程处理转发,不过除了用IO来表示这个线程也想不出来更好的名字了J。可以先参看下 How Chromium Displays Web Pages 上面的介绍,先引用一张上面的图片:                                                (BrowerProcess基本的线程结构)一个页面是怎样被创建的呢?先弄清楚下面几点说明<静态数据概念>:     1:一个BrowerProcess里面保存一个Browser的列表,每个Browser对象代表着一个浏览器窗口。     2:每个Browser对象里面保存一个WebContents列表(这个列表是用了一个TabStripModel的对象来封装),WebContents就是浏览器上面的HTML页面和标签。    3:每个WebContents中包含了一个RenderViewHost对象。这里要多介绍一下WebContents和 RenderViewHost各自的功能:RenderViewHost主要表现的就是一个HTML页面,WebContents不说大家可能也已经猜到 了,它就是管理标签命令和导航命令的(HTML页面以外的消息由它处理)。讲 一些题外话,GOOGLE声明说他们会在将来支持其他程序调用RenderViewHost的功能,这对微软来说是个相当打的挑战,虽然说瘦死的骆驼比马 大,但是GOOGLE会一步步地同食微软的市场,这匹瘦骆驼也无力于健壮的马来竞争,IE只是他们计划中的一个小计划,闲话不多扯了,杀回来继续。     4:每个RenderViewHost被创建的时候它会创建一个RenderProcessHost的对象,并且创建一个Rander进程,RenderProcessHost的对象会等待Rander进程的连接消息。     5:一个RenderProcessHost对象会创建一个ChannelProxy的代理对象(这个对象将被分配到IO线程里面去运 行),ChannelProxy对象的职责是转发Render进程的消息和网络消息(HTTP页面下载),并且把需要网络消息转发给Render进程。 RenderProcessHost对象还会创建另外一个过滤消息的对象ResourceMessageFilter的过滤器,该过滤器会被添加到 ChannelProxy中,此处也是采用上面重复提到的委托伎俩,ChannelProxy有个过滤消息的委托接口类,然后把消息交给由外面派生类 (ResourceMessageFilter)来处理,如果处理了那么就不转发消息给UI线程了,如果没处理,那么转发消息。     6:每个ChannelProxy里面会包含一个真正的IPC:Channel对象,如果看过我上一篇文章的同学肯定还记的这个 IPC:Channel,不就是进行进程间通讯的东东吗。Channel会把接受到的消息转发给ChannelProxy,由ChannelProxy 决定该消息路由到什么地方。另外一点就是ChannelProxy会收到本进程的消息(网络消息和UI消息和其他的消息),这些消息会根据情况被转发给 Render进程。   ChannelProxy在IO线程中是怎么把Message转换为Task的呢?    同学们可能很奇怪,Message和Task都都好像在前面见过,但是他们之间有什么关系呢?    Message是从Render进程那儿接受到的消息,TASK是消息循环中执行的一个任务,IO线程需要把Message转换为TASK发送到UI线 程中去执行,Chrome开发人员定义了一套NewRunnableMethod 的方法,用来把Message转换为相应的TASK,参看basetask.h代码。ChannelProxy里面保存了UI的消息循环对象的指针,然 后通过该对象PostTask系列函数来发送消息到UI线程中。     一个对BrowerProcess里面的进程大概介绍就这样完成了,对上面的6点我们还可以总结出 1,2,3是在UI线程环境中运行的,4,5是在IO线程中运行的,6是IO和UI线程之间交互方式。  /=飘逸的分割线=/     下一章将对RenderProces里面的线程做简单的介绍,有了BrowerProcess的介绍这就简单得多了:)前面写了Chrome消息系统(1)前 比较抽象,这章来点具体的,当然要结合代码来看了!现在我要关注的问题是:一个RenderProcess的消息怎么发送到BrowserProcess进程中的,这个消息走了那些路?注意,所说的IO线程是Browser进程中的IO线程,非Render进程中发的IO。所谓的IO线程主要用来接受网络消息和进程间的消息,我先把网络消息抛到一边,单独分析下RenderProcess进程给BrowserProcess的消息是怎样流动的?通常把网络包分为上行和下行,在这里我把RenderProcess到BrowserProcess称为上行消息,BrowserProcess到RenderProcess的消息称为下行消息,这章只讨论上行消息。需要特别注意的几个类分别是: SiteInstance: 每个SiteInstance对象对应于一个RenderProcessHost,当创建RenderViewHost时会传递一个SiteInstance实例,该RenderViewHost保存在SiteInstance实例的RenderProcessHost对象中。SiteInstance对应于四种启动方式。RenderProcessHost:每个RenderProcessHost对应于一个RenderProcess进程,RenderProcess进程负责渲染所有的RenderProcessHost中的RenderViewHost的页面。WebContents: WebContents包括了RenderViewHost和NavigationController。RenderViewHostManager:存在于WebContents主要保存一个RenderViewHost对象,但是有一种情况比较复杂,那就是当一个Interstitial webpage存在时,它负责加载Interstitial webpage,并切换到用户请求页面。关于Interstitial webpage请参看上上篇文章的解释。由于这种复杂度,这里没有直接采用RenderViewHost而是采用RenderViewHostManager来控制管理。NavigationController: 存在于WebContents中,控制一个TAB的后退,前进,刷新,加载等操作。RenderViewHost:对应于一个HTML页面Channel:  用于进程间通讯。ChannelProxy: 对Channel的代理,并且附加了一些过滤信息ChannelProxy:Context: 封装的ChannelSyncChannel:   扩展了ChannelProxy,使之能支持同步信息。SyncChannel:SyncContext: 对ChannelProxy:Context的同步支持的封装。ResourceDispatcherHost:所有消息将通过ResourceDispatcherHost来过滤,ResourceMessageFilter的消息也会通过ResourceDispatcherHost,ResourceDispatcherHost还过滤网络消息,并且做相应的转发。ResourceMessageFilter: 过滤ChannelProxy的一些相关信息。MessageLoopForIO: 提供支持APC 事件通知的消息循环,这里是支持命名管道的消息。先大致走一趟上行消息的简单流程,然后结合代码仔细分析。消息最先达到的地方当然是Channel这个对象了,Channel是被ChannelProxy:Context所封装,所以消息会被分派到ChannelProxy:Context中,ChannelProxy:Context对象是存在于ChannelProxy中的,ChannelProxy:Contex又把消息提交给了ChannelProxy,ChannelProxy先过滤消息,如果消息没有被过滤掉,把消息推给RenderProcessHost,然后由RenderProcessHost把消息分配给每个相应的RenderViewHost。 上面是上行消息的一个简单的路由过程。其中细节很多,问题也是很多。0:一个TAB页面是怎么被创建的出来的?1:ChannelProxy怎么由UI线程给分派到IO线程中去运行?2:一个命名管道的消息怎么被通知到BrowserProcess进程中的?3:消息是通过什么方法逐渐往上一层传递的?4:ResourceMessageFilter是怎么加进ChannelProxy中的,它会过滤掉什么样的消息,什么消息它会继续转发?5:ResourceMessageFilter和ResourceDispatcherHost有什么瓜葛?一:先来分析第一个问题:一个TAB页面是怎么被创建的出来的?当用户点击浏览器上的添加按钮或者是从一个网页的一个连接来打开一个新的页面,这样一个新的页面就被创建了。一个WebContents对象对应于一个HTML页面和关联该页面的标签,创建一个页面其实就是创建一个WebContents对象。上面提到过RenderViewHostManager 存在于WebContents中,RenderViewHostManager 是用来保RenderViewHost对象的,RenderViewHost对象也是在RenderViewHostManager中被创建的。WebContents的构造函数中会传递一个SiteInstance参数, RenderViewHostManager会创建RenderViewHost,然后把创建的RenderViewHost对象关联到SiteInstance相对应的RenderProcessHost中。仔细看RenderProcessHost的结构会发现,RenderProcessHost中有两个方法:  void Attach(IPC:Channel:Listener* listener, int routing_id);  void Release(int listener_id);用这两个方法来关联和取消关联,具体细节参见前面的UML 类图。这样一个RenderViewHost的对象就被创建并关联到相应的RenderProcessHost中了。二:分析第二个问题:ChannelProxy怎么由UI线程给分派到IO线程中去运行?根据chrome官方技术文档可以看出来,每个RenderProcessHost对应一个RenderProcess,他们之间通过ChannelProxy来通讯的,也就是说RenderProcessHost是通过ChannelProxy和RenderProcess的ChannelProxy来通讯的。RenderProcessHost和RenderProcess分别都拥有一个ChannelProxy,RenderProcessHost和RenderProcess都是通过他们的大使ChannelProxy来沟通的。先抛开RenderProcess和它的大使ChannelProxy,专心来分析RenderProcessHost和它的大使ChannelProxy。

    注意事项

    本文(源码分析.doc)为本站会员(laozhun)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开