Chromium doc: Mojo
https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md
机器翻译+人工简单润色。
从Mojo开始
要在已经支持Mojo的应用程序(如Chrome)中开始使用Mojo,最快的方法是查看您选择的语言(C++[1]、JavaScript[2]或Java[3])的绑定文档,以及MojomIDL和绑定生成器的文档[4]。
如果您正在查找有关创建和/或连接到服务的信息,请参阅顶级服务文档 [5]。
有关将旧的东西转换成新的东西的具体细节,请查看将传统ChromeIPC转换为Mojo的过程 [6]。
[1] https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md#C_Bindings
[2] https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md#JavaScript-Bindings
[3] https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md#Java-Bindings
[4] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/tools/bindings/README.md
[5] https://chromium.googlesource.com/chromium/src/+/master/services/README.md
[6] https://chromium.googlesource.com/chromium/src/+/master/ipc/README.md
系统概述
Mojo是运行时库的集合,提供了公共IPC原语的平台无关抽象、消息IDL格式和绑定库,其中包含针对多种目标语言的代码生成,以方便消息跨越任意进程间和进程内边界。
这里的文档是根据包含Mojo的不同库进行分割的。特征的基本层次如下:
(IMG)
Mojo库分层:底层为核心,顶部为语言绑定,中间为公共系统支持API
Mojo内核
为了使用任何更有趣的高级支持库,如系统API或绑定API,进程必须首先初始化Mojo Core。
进行一次初始化之后,在进程生命周期的剩余时间内一直处于活动状态。
初始化MojoCore有两种方法:通过EmbedderAPI,或者通过动态链接库。
嵌入
许多通过Mojo互连的进程都是嵌入程序,这意味着它们静态地链接到/mojo/core/Embedder目标,并通过调用mojo::core::init()来初始化每个进程中的Mojo支持。
有关更多细节,请参见Mojo CoreEmbedderAPI [1]。
这是一个合理的选择,因为您可以保证所有相互连接的进程二进制文件都链接到完全相同的MojoCore修订版上。
若要支持其他方案,请使用动态链接。
[1] https://chromium.googlesource.com/chromium/src/+/master/mojo/core/embedder/README.md
动态链接
在某些平台上,应用程序还可以依赖动态链接的Mojo Core库(libmojo_core.so或mojo_core.dll),而不是静态链接Mojo Core。
为了利用这一机制,相应的库必须存在于以下文件中:
* 应用程序的工作目录。
* 由mojo_core_Library_path环境变量命名的目录。
* 应用程序在运行时显式命名的目录。
使用动态Mojo Core的应用程序不像嵌入式程序那样调用mojo::core::init(),而是从C系统API调用MojoInitiize()。
此调用将尝试定位(参见上文)并加载一个MojoCore库,以支持进程中后续的MojoAPI使用。
请注意,Mojo Core共享库提供了一个稳定的、向前兼容的C ABI,它可以支持更高级别、公共(而非二进制稳定)系统和绑定API的所有当前和未来版本。
C++
C++ System API [1]提供了一层C+帮助器类和函数,使安全系统API的使用更容易:强类型句柄作用域、同步等待操作、系统句柄包装和展开帮助程序、公共句柄操作,以及更容易监视句柄状态更改的实用程序。
JavaScript
JavaScript System API [2]将Mojo原语公开给JavaScript,涵盖了低级CAPI的所有基本功能。
Java
Java System API [3]提供了用于处理Mojo原语的助手类,涵盖了低级CAPI的所有基本功能。
[1] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/cpp/system/README.md
[2] https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/mojo/README.md
[3] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/java/system/README.md
高级绑定api
通常,开发人员不直接使用原始消息管道I/O,而是定义一些接口集,这些接口用于生成类似于所选择的目标语言的惯用方法调用接口的代码。这是绑定层。
Mojom IDL和绑定生成器
接口是使用MojomIDL [1]定义的,可以将其提供给绑定生成器[2],以生成各种受支持的语言中的代码。
生成的代码管理接口客户端和实现之间消息的序列化和反序列化,简化代码-并最终将消息管道隐藏在接口连接的两侧。
C++绑定
到目前为止,由Mojo定义的最常用的API,C++绑定API [3]公开了一组健壮的特性,用于通过生成的C+绑定代码与消息管道交互,包括对相关绑定端点集、关联接口、嵌套同步IPC、版本控制、坏消息报告、任意消息筛选器注入和方便的测试工具的支持。
[1] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/tools/bindings/README.md
[2] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/tools/bindings/README.md
[3] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/cpp/bindings/README.md
JavaScript绑定。
JavaScript binding API [1]提供了帮助器类,用于处理由绑定生成器发出的JavaScript代码。
Java绑定。
Java Bindings API [2]提供了帮助器类,用于处理由绑定生成器发出的Java代码。
[1] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/js/README.md
[2] https://chromium.googlesource.com/chromium/src/+/master/mojo/public/java/bindings/README.md
常见问题。
为什么不是protobuf或者其他的?
对于这个问题,可能有很多不错的答案,但最重要的是,一个有用的IPC机制必须支持跨越进程边界的本地对象句柄(例如,文件描述符)的传输。
其他支持此功能的非新IPC(例如d-bus)也有其自身的重大缺陷。
信息管道运行时代价很高吗?
不。作为实现细节,创建消息管道实质上是生成两个随机数,并将它们填充到一个哈希表中,以及一些很小的堆分配。
所以说真的,我能创造出成千上万个这样的东西吗?
是。没人会介意的。创造数以百万计的人,如果你愿意的话。(好吧,但也许不需要。)。
Mojo的性能特点是什么?
与Chrome中的旧IPC相比,进行Mojo调用大约要快1/3,使用的上下文切换也少1/3。完整的数据可在这里获得。 (https://docs.google.com/document/d/1n7qYjQ5iy8xAkQVMYGqjIy_AXu2_JJtMoAcOOupO_jQ/edit)
我可以使用进程内消息管道吗?
是的,而且消息管道的使用是相同的,不管管道是否真的跨越了进程边界-事实上,这个细节是有意模糊的。
不跨越进程边界的消息管道是高效的:发送的消息永远不会被复制,一端的写操作将同步地修改另一端的消息队列。
例如,当使用生成的C++绑定时,最终的结果是一个线程上的InterfacePtr向另一个线程上的绑定(甚至同一个线程)发送消息,实际上是一个PostTask到绑定的TaskRunner,同时增加了序列化、反序列化、验证和一些内部路由逻辑的开销(但通常很小)。