chromium 之 ipc (mojo) 消息机制

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)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值