Mojo
chromium 中的 ipc(进程间通信) 采用 mojo,使用双向的消息管道,每个终结点都有一个传入消息队列,并在一个终结点上写入消息,有效地将该消息排队到另一个 (对等 ) 终结点上。
通过 mojom 文件采用强类型消息来描述并记录接口。(和protobufs类似,可参考)
给定一个 Mojom 接口和管道消息,一端作为远程通过接口发送消息,另一端则作为接收端接收消息。由于 Mojo 采用双向通信的机制,作为发送消息的远程端,也可能接收来自接收端的消息。
为了处理接收到的消息,接收端会绑定接口消息和指定接口消息的具体实现方法。
举例:定义一个接口
该例子是从 render 进程发送一个 Ping 消息,发送到 主进程(browser) 的 RenderFrameHostImpl
接口。步骤:
1. 定义一个 Mojom 接口
2. 为该接口创建对应的管道消息
3. 创建绑定关系及绑定方法的实现
(如果有 chromium 开发环境的小伙伴,可以实际操作一番~ chromium环境搭建链接:windows下搭建编译chromium的开发环境_二七-CSDN博客)
1. 创建 mojom 接口
创建新的 Mojom 文件,定义ping接口,mojom路径:src/example/public/mojom/ping_responder.mojom
// src/example/public/mojom/ping_responder.mojom
module example.mojom;
interface PingResponder {
// Receives a "Ping" and responds with a random integer.
Ping() => (int32 random);
};
创建对应的 build.gn 文件,路径:src/example/public/mojom/BUILD.gn
# src/example/public/mojom/BUILD.gn
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [ "ping_responder.mojom" ]
}
将 ping_responder.mojom 的 build.gn 导入到工程, 在 src\content\browser\BUILD.gn 中添加代码:
jumbo_source_set("browser") {
# Only the public target should depend on this. All other targets (even
# internal content ones) should depend on the public one.
// ...
deps = [
...
// 添加在此处的结尾
"//example/public/mojom",
]
...
2. 创建 Pipe 管道
在 renderer 的逻辑代码中,创建管道 (注:最好放在生命周期长的对象中)
#include "example/public/mojom/ping_responder.mojom.h"
mojo::Remote<example::mojom::PingResponder> ping_responder;
mojo::PendingReceiver<example::mojom::PingResponder> receiver =
ping_responder.BindNewPipeAndPassReceiver();
在 renderer 的逻辑代码中,发送消息及实现回调 (注:最好放在生命周期长的对象中)
#include "example/public/mojom/ping_responder.mojom.h"
void OnPong(int32_t num) {}
ping_responder_->Ping(base::BindOnce(&OnPong));
3.实现Mojo消息的绑定和接收
在 render_frame_host_impl.h 中添加 Class PingResponderImpl
....
#include "example/public/mojom/ping_responder.mojom.h"
....
class PingResponderImpl : example::mojom::PingResponder {
public:
explicit PingResponderImpl(mojo::PendingReceiver<example::mojom::PingResponder> receiver) ;
PingResponderImpl(const PingResponderImpl&) = delete;
PingResponderImpl& operator=(const PingResponderImpl&) = delete;
~PingResponderImpl() override ;
// example::mojom::PingResponder:
void Ping(PingCallback callback) override ;
private:
mojo::Receiver<example::mojom::PingResponder> receiver_;
};
class RenderFrameHostImpl
...
void GetPingResponder(mojo::PendingReceiver<example::mojom::PingResponder> receiver);
...
private:
...
std::unique_ptr<PingResponderImpl> ping_responder_;
...
};
在 render_frame_host_impl.h 中添加实现
PingResponderImpl::PingResponderImpl(mojo::PendingReceiver<example::mojom::PingResponder> receiver)
: receiver_(this, std::move(receiver)) {}
PingResponderImpl::~PingResponderImpl() {}
// example::mojom::PingResponder:
void PingResponderImpl::Ping(PingCallback callback) {
// Respond with a random 4, chosen by fair dice roll.
std::move(callback).Run(4);
}
void RenderFrameHostImpl::GetPingResponder(
mojo::PendingReceiver<example::mojom::PingResponder> receiver) {
ping_responder_ = std::make_unique<PingResponderImpl>(std::move(receiver));
}
在 browser_interface_binders.cc 中添加注册
void PopulateFrameBinders(RenderFrameHostImpl* host,
mojo::BinderMap* map) {
...
// Register the handler for PingResponder.
map->Add<example::mojom::PingResponder>(base::BindRepeating(
&RenderFrameHostImpl::GetPingResponder, base::Unretained(host)));
}
大功告成。在 chromium 中加入以上代码后,就可以实现 mojo 的 通信例子。