Chromium的线程模型和消息循环机制一直是其很有亮点也非常值得学习的一部分,关于这部分的工作原理网上有很多好文章,比如这篇、这篇还有这篇。但是这几篇文章基本是站在一定的高度上来概括其思想,而深入到代码里还有一些流程及细节问题,在此略做总结。
首先,在线程启动时基本会按以下流程来启动消息循环:
#1base::MessagePumpLibevent::Run base/message_pump_libevent.cc:243
#2MessageLoop::RunInternal base/message_loop.cc:419
#3MessageLoop::RunHandler base/message_loop.cc:392
#4base::RunLoop::Run base/run_loop.cc:45
#5MessageLoop::Run base/message_loop.cc:299
#6base::Thread::Run base/threading/thread.cc:133
#7content::BrowserThreadImpl::IOThreadRun content/browser/browser_thread_impl.cc:149
#8content::BrowserThreadImpl::Run content/browser/browser_thread_impl.cc:177
#9base::Thread::ThreadMain base/threading/thread.cc:169
#10ThreadFunc base/threading/platform_thread_posix.cc:65
#11__thread_entry ()
#12pthread_create ()
这是Browser进程的IO线程启动时的调用堆栈,其他线程的启动也与此类似(UI线程除外)。可以看到,实际的消息循环是在MessagePump类的run函数中进行的,如果有任务则执行任务,没有任务则在此run函数中等待。
UI线程是比较特殊的,它是主线程,需要处理各种与用户的交互,所以它是不能阻塞,且与平台相关的。在各个平台下UI线程的MessagePumpForUI类的实现是不同的,它也不使用MessageLoop提供的消息循环,而是使用平台提供的消息循环。比如chromiumfor
android使用的是android提供的handler那一套。
MessageLoop类主要维持循环中的各个队列,而真正处理各种等待、唤醒、阻塞和处理事件的则是在MessagePump中进行的。这里用到了一个第三方库libevent来进行事件注册、阻塞、唤醒等操作。
MessagePump在初始化时(init函数)会注册事件,然后在run函数循环过程中会等待该事件。其中MessagePumpDefault最简单,它只能处理Task任务,所以它run时直接阻塞在一个条件变量上即可,然后等待ScheduleWork函数来唤醒它。ScheduleWork什么时候调用呢?已经很明确了,在有人调用MessageLoop::AddToIncomingQueue向该线程的消息incoming队列中放任务时,就要调用MessagePumpDefault的ScheduleWork函数。
MessagePumpLibevent类的处理就比较复杂了,它除了处理Task任务,还要处理IPC消息,系统消息等。这时需要同时监听多个事件,就不能直接用条件变量了。虽然是用libevent库实现的,但底层应该是用类似select系统调用,来同时监听多个文件描述符,来达到监听多个事件的目的。
其中Task任务会阻塞在一个管道的read函数上,在init函数中创建的该管道,然后在OnWakeup函数read,如果管道中没有数据在这里会阻塞住。在ScheduleWork函数中会像管道中写数据以唤醒OnWakeup。至于ScheduleWork怎么调用的就不用多说了吧。
而对IPC消息的监听会在WatchFileDescriptor函数注册需要监听的套接字,而该函数是在channel类的AcceptConnect函数调用过来的,具体流程可参见这里。若是套接字有数据到达,触发事件后会调用OnLibeventNotification函数来处理IPC消息,关于IPC消息的处理流程还是参见这里。
MessagePumpForUI类前面已经说过,使用系统提供的消息循环。也就是说其run函数其实没有作用,而ScheduleWork也会转发到系统消息循环。至于其机制,可参见android异步通信机制。
至此chromium的消息循环机制的流程就大体上有了,但实际中更为复杂一些,比如任务也分为PostTask,PostDelayedTask,PostNonNestableTask,PostNonNestableDelayedTask几种,相应的任务队列也分为多个。
关于任务是怎么封装的又是另外一个值得学习的地方,以后有时间继续总结。
分享到:
相关推荐
描述了chromium开源浏览器中的安全机制,沙箱保护,多进程机制
chromium message loop 封装使用的一个跨线程通信demo,内含有chromium base库(部分抽取),以及消息循环跨线程通信的一个使用案例。
render 进程如何处理事件消息?我们下面就通过分析代码来一一探明。 chromium 系统有多个平台的实现,而每个平台都有自己不同的事件管理方式,chromium 也会有一些平台相关的代码。本文目前主要是研究 Linux 平台...
chromium命令行参数1
ungoogled-chromium是Google Chromium,不依赖于Google Web服务。 ungoogled-chromium尽可能保留默认的Chromium体验。与其他具有Web浏览器愿景的其他Chromium分支不同,ungoogled-chromium本质上是Chromium的直接...
chromium-linux.zip
SwitchyOmega-Chromium
该文件属于Chromium 58版本的编译配置文档,其中,包含每一项参数的说明。 请注意,该文档是通过gn args --list out/debug生成的,如果你已下载Chromium源码,可以手动生成,不必下载。
chromium离线安装版49 x86 32位windows xp 2003 亲测好用.chromium 不会默认上传您的用户数据,且性能比同版本chrome强10%。差不多可以说算得上是xp 2003 下最好用的 浏览器了
SwitchyOmega_Chromium插件
LICENSES.chromium
Chromium Nightly Updater 1.1
SwitchyOmega_Chromium.crx
Chromium浏览器官方版是一个由Google主导开发的网页浏览器,Chromium浏览器官方版是Google为发展Google Chrome而开启的计划,所以Chromium浏览器相当于Chrome的工程版或称实验版,新功能会率先在Chromium上实现,待...
Chromium离线安装包,适用于树莓派。我的博客中有教程。
chromium开发教程.docx
断断续续下载chromium代码花了1周左右,代码约15G左右,其中遇到power shell的问题,遇到python的问题。最终编译花了11:30分。相比于Linux下的编译慢很多,系统运行的稳定性和速度也差很多。打算研究源码,一起分享...
Chromium网页渲染技术,更多信息点击进入:http://0xcc0xcd.com
SwitchyOmega_Chromium.zip
chromium的media模块代码,主要用于学习播放器的架构,学学chromium的播放引擎架构