chromium 之 ipc (mojo) 消息机制

chromium 专栏收录该内容
12 篇文章 3 订阅

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 的 通信例子。

参考官方文档:Intro to Mojo & Services (googlesource.com)

  • 1
    点赞
  • 0
    评论
  • 4
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏作者

池塘码农

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值