部分内容来源于本文:http://blog.csdn.net/qq295445028/article/details/7993051
一、消息格式
如果说,多线程模式下,对数据的访问开销来自于锁,那么在多进程模式下,大部分的额外开销都来自于进程间的消息拆装和传递。不论怎么样的模式,只要进程不同,消息的打包,序列化,反序列化,组包,都是不可避免的工作。
在Chrome中,IPC之间的通信消息,都是派生自IPC::Message类的。对于消息而言,序列化和反序列化是必须要支持的,Message的基类Pickle,就是干这个活的。Pickle提供了一组的接口,可以接受int,char,等等各种数据的输入,但是在Pickle内部,所有的一切都没有区别,都转化成了一坨二进制流。这个二进制流是32位齐位的,比如你只传了一个bool,也是最少占32位的,同时,Pickle的流是有自增逻辑的(就是说它会先开一个Buffer,如果满了的话,会加倍这个Buffer...),使其可以无限扩展。Pickle本身不维护任何二进制流逻辑上的信息,这个任务交到了上级处理(后面会有说到...),但Pickle会为二进制流添加一个头信息,这个里面会存放流的长度,Message在继承Pickle的时候,扩展了这个头的定义,完整的消息格式如下:
其中,黄色部分是包头,定长96个bit,绿色部分是包体,二进制流,由payload_size指明长度。从大小上看这个包是很精简的了,除了routing位在消息不为路由消息的时候会有所浪费。消息本身在有名管道中是按照二进制流进行传输的(有名管道可以传输两种类型的字符流,分别是二进制流和消息流...),因此由payload_size + 96bits,就可以确定是否收了一个完整的包。。。
从逻辑上来看,IPC消息分成两类,一类是路由消息(routed message),还有一类是控制消息(control message)。路由消息是私密的有目的地的,系统会依照路由信息将消息安全的传递到目的地,不容它人窥视;控制消息就是一个广播消息,谁想听等能够听得到。
control消息与具体View无关,它将被RenderProcess
或者RenderProcessHost
处理,比如请求资源和修改剪切板是与具体view无关的,因此属于control消息。Routed消息的一个例子是
通知某个view以绘制区域。
二、消息声明
一个标准的IPC消息定义应该是类似于这样的:
classSomeMessage
: public IPC::Message
{
public:
enum { ID = ...; }
SomeMessage(SomeType & data)
: IPC::Message(MSG_ROUTING_CONTROL, ID, ToString(data))
{...}
...
};
大概意思是这样的,你需要从Message(或者其他子类)派生出一个子类,该子类有一个独一无二的ID值,该子类接受一个参数,你需要对这个参数进行序列化。两个麻烦的地方看的很清楚,如果生成独一无二的ID值?如何更方便的对任何参数可以自动的序列化?
在Chrome中,解决这两个问题的答案,就是宏 + 模板。Chrome为每个消息安排了一种ID规格,用一个16bits的值来表示,高4位标识一个Channel,低12位标识一个消息的子id,也就是说,最多可以有16种Channel存在不同的进程之间,每一种Channel上可以定义4k的消息。目前,Chrome已经用掉了8种Channel(如果A、B进程需要双向通信,在Chrome中,这是两种不同的Channel,需要定义不同的消息,也就是说,一种双向的进程通信关系,需要耗费两个Channel种类...),他们已经觉得,16bits的ID格式不够用了,在将来的某一天,估计就被扩展成了32bits的。书归正传,Chrome是这么来定义消息ID的,用一个枚举类,让它从高到低往下走,就像这样:
enumSomeChannel_MsgType
{
SomeChannelStart = 5 << 12,
SomeChannelPreStart = (5 << 12) - 1,
Msg1,
Msg2,
...
MsgN,
SomeChannelEnd
};
这是一个类型为5的Channel的消息ID声明,由于指明了最开始的两个值,所以后续枚举的值会依次递减,如此,只要维护Channel类型的唯一性,就可以维护所有消息ID的唯一性了(当然,前提是不能超过消息上限...)。但是,定义一个ID还不够,你还需要定义一个使用该消息ID的Message子类。这个步骤不但繁琐,最重要的,是违反了DIY原则,为了添加一个消息,你需要在两个地方开工干活,是可忍孰不可忍,于是Google祭出了宏这颗原子弹,需要定义消息,格式如下:
IPC_BEGIN_MESSAGES(PluginProcess,3)
IPC_MESSAGE_CONTROL2(PluginProcessMsg_CreateChannel,
int /*process_id */,
HANDLE /*renderer handle */)
IPC_MESSAGE_CONTROL1(PluginProcessMsg_ShutdownResponse,
bool /*ok to shutdown */)
IPC_MESSAGE_CONTROL1(PluginProcessMsg_PluginMessage,
std::vector<uint8> /* opaque data */)
IPC_MESSAGE_CONTROL0(PluginProcessMsg_BrowserShutdown)
IPC_END_MESSAGES(PluginProcess)
这是Chrome中,定义PluginProcess消息的宏,我挖过来放在这了,如果你想添加一条消息,只需要添加一条类似与IPC_MESSAGE_CONTROL0东东即可,这说明它是一个控制消息,参数为0个。你基本上可以这样理解,IPC_BEGIN_MESSAGES就相当于完成了一个枚举开始的声明,然后中间的每一条,都会在枚举里面增加一个ID,并声明一个子类。
Render和Browser之间的消息都声明在render_messages.h。有2个部分——View和ViewHost。
若要声明一个ViewHost、与view相关的(routed)消息,并包含URL和整型2个参数:
IPC_MESSAGE_ROUTED2(ViewHostMsg_MyMessage,GURL, int)
若要声明一个View、control消息:
IPC_MESSAGE_CONTROL0(ViewMsg_MyMessage)
通过宏和模板,你可以很简单的声明一个消息,这个消息可以传入各式各样的参数(这里用到了夸张的修辞手法,其实,只要是模板实现的自动化,永远都是有限制的,在Chrome的模板实现中,参数数量不要超过5个,类型需要是基本类型、STL容器等,在不BT的场合,应该够用了...)
有时候消息中包含太多值,我们需要定义一个专门的结构来封装这些值。例如ViewMsg_Navigate
消息,render_messages.h
文件中定义了ViewMsg_Navigate_Params
结构,同时也定义了ParamTraits
对该结构的特化版本
同步消息声明:
同步消息使用IPC_SYNC_MESSAGE_*宏来声明。这个宏含有输入和返回参数(非同步消息没有返回参数的概念)。如果控制函数有2个输入参数,1个返回参数,则需要在宏后面加2_1。:
IPC_SYNC_MESSAGE_CONTROL2_1(SomeMessage, // Message name
GURL, //input_param1
int, //input_param2
std::string); //result
同样的,也有路由到view的消息用IPC_SYNC_MESSAGE_ROUTED2_1来得到。也可以没有输入和返回参数。没有返回参数主要用于render必须等待browser做某事,但不需要返回值。比如确定绘制和剪切板操作。
三、消息发送
RenderWidgetHost
类
(RenderViewHost基类)提供了send函数
消息通过指针发送,并在被分派之后由IPC层来删除。因此可以new一个消息对象来传给send函数
Send(new ViewMsg_StopFinding(routing_id_));
注意,必须指定routing_id_以便消息能够被正确的View/ViewHost接收。RenderWidgetHost类和RenderWidget类(RenderView基类)都有routing_id_
可以使用。
关于routing_id_,若其值为MSG_ROUTING_NONE则该消息不会发送,或被接收端忽略。若其值为MSG_ROUTING_CONTROL,则发送的是CONTROL类型的消息,与具体View无关。
消息发送流程:
四、消息处理
通过实现IPC::Channel::Listener接口来处理消息,该接口中最重要的函数是OnMessageReceived。在这个函数中我们有很多宏来简化消息处理。示例如下:
MyClass::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(MyClass, message)
// Will call OnMyMessage with the message. The parameters of the message will be unpacked for you.
IPC_MESSAGE_HANDLER(ViewHostMsg_MyMessage, OnMyMessage)
...
IPC_MESSAGE_UNHANDLED_ERROR() // This will throw an exception for unhandled messages.
IPC_END_MESSAGE_MAP()
}
// This function will be called with the parameters extracted from the ViewHostMsg_MyMessage message.
MyClass::OnMyMessage(const GURL& url, int something) {
...
}
也可以通过使用IPC_DEFINE_MESSAGE_MAP宏来实现函数声明,在这种情况下,不指定一个消息变量名,它会声明一个OnMessageReceived的函数在给定的类,并实现其内容。
其他宏:
IPC_MESSAGE_FORWARD:类似于IPC_MESSAGE_HANDLER
,但是可以指定您自己的类来将消息发送过去,而不是把它发送到当前类:
IPC_MESSAGE_FORWARD(ViewHostMsg_MyMessage, some_object_pointer, SomeObject::OnMyMessage)
IPC_MESSAGE_HANDLER_GENERIC:这使您可以编写自己的代码,但你自己必须从消息中获取参数。
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_MyMessage,printf("Hello, world, I got the message."))
分享到:
相关推荐
chromium for android
描述了chromium开源浏览器中的安全机制,沙箱保护,多进程机制
AndroidChromium 简单的介绍 谷歌浏览器android版源程序 该项目是世界一流的android体系结构 澄清项目业务逻辑可以完全适合国内公司工程师 该项目将长期跟踪和更新Google浏览器内核版本,欢迎加入星号 注意 如果您...
众所周知, chromium 是多进程框架的,整个 chromium 浏览器包括四类进程: browse 主进程、 render 渲染进程、 GPU 进程和插件进程。本文所要讲述的 chromium 事件处理流程 主要牵涉到其中的两种进程: browser ...
进程间通信,叫做IPC(Inter-Process Communication),在Chrome不多的文档中,有一篇就是介绍这个的,在这里。Chrome最主要有三类进程,一类是Browser主进程,我们一直尊称它老人家为老大;还有一类是各个Render...
Android WebView wrapper based on chromium Notice This is just a experimental project, don't use it in product. If you have problem when git pull, please re-clone this repository. I updated the commits...
Chromium on Android does not have automatic updates like Chrome. This app automatically installs Chromium and keeps it updated. You can choose to install the stable version, or the very latest version...
chromium离线安装版49 x86 32位windows xp 2003 亲测好用.chromium 不会默认上传您的用户数据,且性能比同版本chrome强10%。差不多可以说算得上是xp 2003 下最好用的 浏览器了
源码参考,欢迎下载
也是网上看到的,android4.4的webview基于chromium,各个类的关系图
android chromium chromium 最新 113.0.5648.0版本
分包压缩上传,共计12个压缩包。 可直接编译。Ubuntu20.04环境编译步骤: 解压: cat 108.0.5359....详情参考:https://chromium.googlesource.com/chromium/src/+/108.0.5359.156/docs/android_build_instructions.md
chromium for android系列文章用图
Date: May 13, 2016 CEF Version: 3.2623.1401.gb90a3be Chromium Verison: 49.0.2623.110 最后一个支持winxp版本
谷歌浏览器安卓版源码项目,本项目是世界级的安卓架构。
chromium浏览器linux版本,版本号1000548,2022年5月版本,现代语言兼容
delphi 调用google chrome浏览器, Chromium(CEF3)组件最新版本,可代替webbrowser浏览器, 支持html5,与UC/360浏览器同等内核,是开发WEB终端显示最好用的浏览器组件、支持DELPHI7 DELPHI2010 XE2,XE10 ,XE8 等
分包压缩上传,共计12个压缩包。 可直接编译。Ubuntu20.04环境编译步骤: 解压: cat 108.0.5359....详情参考:https://chromium.googlesource.com/chromium/src/+/108.0.5359.156/docs/android_build_instructions.md
AndroidChromium 简单的介绍 谷歌浏览器android版源程序 该项目是世界一流的android体系结构 澄清项目业务逻辑可以完全适合国内公司工程师 该项目将长期跟踪和更新Google浏览器内核版本,欢迎加入星号 注意 如果您...
它捕获通过“进程间通信(IPC)”原语发送的数据,并将其发送到解剖。使用此工具我能看到什么? 消息(端口,节点,邀请,句柄等) (实际的.mojom IDL方法调用) 控制消息(读/写X字节) 音频同步消息( \pipe\...