chromium通信系统-ipcz系统(十一)-mojo binding

这篇具有很好参考价值的文章主要介绍了chromium通信系统-ipcz系统(十一)-mojo binding。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于mojo binding的官方文档为mojo docs。 由于比较复杂,这里只做简单源码分析。

我们知道要实现rpc,必须实现客户端和服务端。 mojo 实现了一套领域语言,通过领域语言描述接口和数据, 再通过特有编译器编译成c++代码。 这个过程会生成Mojo对象, 我们以content/common/child_process.mojom 为例子来分析。


interface ChildProcess {
 ......

  // Requests that the process bind a receiving pipe targeting the service
  // interface named by |receiver|.
  //
  // TODO(crbug.com/977637): Rename this to |RunService()| once the above method
  // is removed.
  BindServiceInterface(mojo_base.mojom.GenericPendingReceiver receiver);

  // Requests that the process bind a receiving pipe targeting the interface
  // named by |receiver|. Unlike |BindServiceInterface()| this may be used to
  // bind arbitrary interfaces on many different types of child processes.
  // Calls to this method generally end up in
  // |ChildThreadImpl::OnBindReceiver()|.
  //
  // Whether or not the interface type encapsulated by |receiver| is supported
  // depends on the process type and potentially on the Content embedder.
  BindReceiver(mojo_base.mojom.GenericPendingReceiver receiver);
  ......
};

我们删除一些接口,总体定义如下。生成带c++代码如下。
out/Default/gen/content/common/child_process.mojom.h



class CONTENT_EXPORT ChildProcess
    : public ChildProcessInterfaceBase {
 public:
  ......
  // 接口的名字
  static const char Name_[];
  // 方法表,用于将消息序号转化为处理函数
  static IPCStableHashFunction MessageToMethodInfo_(mojo::Message& message);
  // 方法名称表
  static const char* MessageToMethodName_(mojo::Message& message);
  // 协议版本
  static constexpr uint32_t Version_ = 0;
  static constexpr bool PassesAssociatedKinds_ = false;
  // 是否包含不可中断的方法
  static constexpr bool HasUninterruptableMethods_ = false;

  using Base_ = ChildProcessInterfaceBase;
  // 代理对象,用于客户端调用
  using Proxy_ = ChildProcessProxy;

  template <typename ImplRefTraits>
  // 用于指向服务端实现
  using Stub_ = ChildProcessStub<ImplRefTraits>;
  
  // 请求校验器
  using RequestValidator_ = ChildProcessRequestValidator;
  // 回复校验器
  using ResponseValidator_ = mojo::PassThroughFilter;
  // 方法版本列表
  enum MethodMinVersions : uint32_t {
    kProcessShutdownMinVersion = 0,
    kSetIPCLoggingEnabledMinVersion = 0,
    kGetBackgroundTracingAgentProviderMinVersion = 0,
    kEnableSystemTracingServiceMinVersion = 0,
    kCrashHungProcessMinVersion = 0,
    kRunServiceDeprecatedMinVersion = 0,
    kBindServiceInterfaceMinVersion = 0,
    kBindReceiverMinVersion = 0,
    kSetPseudonymizationSaltMinVersion = 0,
  };
 ......
 // 下面是方法声明
  virtual ~ChildProcess() = default;

  ......
  virtual void BindServiceInterface(::mojo::GenericPendingReceiver receiver) = 0;

  
  virtual void BindReceiver(::mojo::GenericPendingReceiver receiver) = 0;

  ......
};

生成的c++ 类除了方法声明之外,还包括如下信息:

  • Name_接口名称
  • MessageToMethodInfo_: 方法表,通过收到的消息找到对应的rpc方法。
  • Proxy_ 代理对象,通过代理对象调用具体方法组装消息,发送给服务端。(包括方法名称,参数等,用于调用服务端对应方法)
  • Stub_ 用于描述服务端,指向服务端具体实现。
  • RequestValidator_ 请求校验。
  • ResponseValidator_ 响应校验。

通过官方文档我们知道通过Remote 调用服务端方法。 来看一下Remote 是如何实现的。
mojo/public/cpp/bindings/remote.h

 887 void ChildProcessProxy::BindServiceInterface(
 888     ::mojo::GenericPendingReceiver in_receiver) {
 889 #if BUILDFLAG(MOJO_TRACE_ENABLED)
 890   TRACE_EVENT1(
 891     "mojom", "Send content::mojom::ChildProcess::BindServiceInterface", "input_parameters",
 892     [&](perfetto::TracedValue context){
 893       auto dict = std::move(context).WriteDictionary();
 894       perfetto::WriteIntoTracedValueWithFallback(
 895            dict.AddItem("receiver"), in_receiver,
 896                         "<value of type ::mojo::GenericPendingReceiver>");
 897    });
 898 #endif
 899   const bool kExpectsResponse = false;
 900   const bool kIsSync = false;
 901   const bool kAllowInterrupt = true;
 902 
 903   const uint32_t kFlags =
 904       ((kExpectsResponse) ? mojo::Message::kFlagExpectsResponse : 0) |
 905       ((kIsSync) ? mojo::Message::kFlagIsSync : 0) |
 906       ((kAllowInterrupt) ? 0 : mojo::Message::kFlagNoInterrupt);
 907 
 908   mojo::Message message(
 909       internal::kChildProcess_BindServiceInterface_Name, kFlags, 0, 0, nullptr);
 910   mojo::internal::MessageFragment<
 911       ::content::mojom::internal::ChildProcess_BindServiceInterface_Params_Data> params(
 912           message);
 913   params.Allocate();
 914   mojo::internal::MessageFragment<
 915       typename decltype(params->receiver)::BaseType> receiver_fragment(
 916           params.message());
 917   mojo::internal::Serialize<::mojo_base::mojom::GenericPendingReceiverDataView>(
 918       in_receiver, receiver_fragment);
 919   params->receiver.Set(
 920       receiver_fragment.is_null() ? nullptr : receiver_fragment.data());
 921   MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
 922       params->receiver.is_null(),
 923       mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
 924       "null receiver in ChildProcess.BindServiceInterface request");
 925 
 926 #if defined(ENABLE_IPC_FUZZER)
 927   message.set_interface_name(ChildProcess::Name_);
 928   message.set_method_name("BindServiceInterface");
 929 #endif
 930   // This return value may be ignored as false implies the Connector has
 931   // encountered an error, which will be visible through other means.
 932   ::mojo::internal::SendMojoMessage(*receiver_, message);
 933 }

BindServiceInterface 的主要作用就是组装消息,然后发送。 这里908-909行创建Message的时候指定的消息名称为internal::kChildProcess_BindServiceInterface_Name, 用于指示服务端调用哪个方法。 这里932行receiver_ 持有一个portal,可以将数据写出去。

我们再看服务端怎么处理消息:

259 // Implements the mojom ChildProcess interface and lives on the IO thread.
260 class ChildThreadImpl::IOThreadState
261     : public base::RefCountedThreadSafe<IOThreadState>,
262       public mojom::ChildProcess {
     ......
358 
359   void BindServiceInterface(mojo::GenericPendingReceiver receiver) override {
360     if (service_binder_)
361       service_binder_.Run(&receiver);
362 
363     if (receiver) {
364       main_thread_task_runner_->PostTask(
365           FROM_HERE, base::BindOnce(&ChildThreadImpl::BindServiceInterface,
366                                     weak_main_thread_, std::move(receiver)));
367     }
368   }
369 
370   void BindReceiver(mojo::GenericPendingReceiver receiver) override {
371     if (wait_for_interface_binders_) {
372       pending_binding_requests_.push_back(std::move(receiver));
373       return;
374     }
375 
376     if (interface_binders_.TryBind(&receiver))
377       return;
378 
379     main_thread_task_runner_->PostTask(
380         FROM_HERE, base::BindOnce(&ChildThreadImpl::OnBindReceiver,
381                                   weak_main_thread_, std::move(receiver)));
382   }
383 
      ......

457   mojo::Receiver<mojom::ChildProcess> receiver_{this};
458 
459   // Binding requests which should be handled by |interface_binders|, but which
460   // have been queued because |allow_interface_binders_| is still |false|.
461   std::vector<mojo::GenericPendingReceiver> pending_binding_requests_;
462 };

ChildThreadImpl::IOThreadState 实现了mojom::ChildProcess接口。 它持有了一个receiver_对象, 该对象持有portal一端, 用于处理对端发送的消息。

我们具体来看 mojo::Receivermojom::ChildProcess 的实现。

template <typename Interface,
          typename ImplRefTraits = RawPtrImplRefTraits<Interface>>
class Receiver {
......
      explicit Receiver(ImplPointerType impl) : internal_state_(std::move(impl)) {}
......
 private:
  internal::BindingState<Interface, ImplRefTraits> internal_state_;
}

Receiver 的参数为ChildThreadImpl::IOThreadState实例。 然后初始化internal_state_变量。internal_state_类型展开宏之后为nternal::BindingState<mojom::ChildProcess, RawPtrImplRefTraitsmojom::ChildProcess> internal_state_。

template <typename Interface, typename ImplRefTraits>
class BindingState : public BindingStateBase {
 public:
  using ImplPointerType = typename ImplRefTraits::PointerType;

  explicit BindingState(ImplPointerType impl) {
    stub_.set_sink(std::move(impl));
  }

......
}

这里stub_成员变量为 typename Interface::template Stub_ stub_;展开宏为
mojom::ChildProcess::Stub_ stub_, 也就是ChildProcessStub。 我们看一下它的实现以及set_sink 方法。
out/Default/gen/content/common/child_process.mojom.h


template <typename ImplRefTraits =
              mojo::RawPtrImplRefTraits<ChildProcess>>
class ChildProcessStub
    : public mojo::MessageReceiverWithResponderStatus {
 public:
........
  void set_sink(ImplPointerType sink) { sink_ = std::move(sink); }
  ImplPointerType& sink() { return sink_; }

  bool Accept(mojo::Message* message) override {
    if (ImplRefTraits::IsNull(sink_))
      return false;
    return ChildProcessStubDispatch::Accept(
        ImplRefTraits::GetRawPointer(&sink_), message);
  }

  bool AcceptWithResponder(
      mojo::Message* message,
      std::unique_ptr<mojo::MessageReceiverWithStatus> responder) override {
    if (ImplRefTraits::IsNull(sink_))
      return false;
    return ChildProcessStubDispatch::AcceptWithResponder(
        ImplRefTraits::GetRawPointer(&sink_), message, std::move(responder));
  }

 private:
  ImplPointerType sink_;
};

set_sink方法实际设置成员变量sink_, 实际指向ChildThreadImpl::IOThreadState实例。 当receiver收到消息后会调用Accept(异步)方法或者AcceptWithResponder(同步返回结果)方法。

Accept方法调用ChildProcessStubDispatch::Accept方法,第一个参数为sink_, 第二个参数为消息体。我们来看ChildProcessStubDispatch::Accept 方法
out/Default/gen/content/common/child_process.mojom.cc

1021 // static
1022 bool ChildProcessStubDispatch::Accept(
1023     ChildProcess* impl,
1024     mojo::Message* message) {
1025   switch (message->header()->name) {
         .......
1182     case internal::kChildProcess_BindServiceInterface_Name: {
1183 
1184       DCHECK(message->is_serialized());
1185       internal::ChildProcess_BindServiceInterface_Params_Data* params =
1186           reinterpret_cast<internal::ChildProcess_BindServiceInterface_Params_Data*>(
1187               message->mutable_payload());
1188 
1189       bool success = true;
1190       ::mojo::GenericPendingReceiver p_receiver{};
1191       ChildProcess_BindServiceInterface_ParamsDataView input_data_view(params, message);
1192 
1193       if (success && !input_data_view.ReadReceiver(&p_receiver))
1194         success = false;
1195       if (!success) {
1196         ReportValidationErrorForMessage(
1197             message,
1198             mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
1199             ChildProcess::Name_, 6, false);
1200         return false;
1201       }
1202       // A null |impl| means no implementation was bound.
1203       DCHECK(impl);
1204       impl->BindServiceInterface(
1205 std::move(p_receiver));
1206       return true;
1207     }
1208     case internal::kChildProcess_BindReceiver_Name: {
1209 
1210       DCHECK(message->is_serialized());
1211       internal::ChildProcess_BindReceiver_Params_Data* params =
1212           reinterpret_cast<internal::ChildProcess_BindReceiver_Params_Data*>(
1213               message->mutable_payload());
1214 
1215       bool success = true;
1216       ::mojo::GenericPendingReceiver p_receiver{};
1217       ChildProcess_BindReceiver_ParamsDataView input_data_view(params, message);
1218 
1219       if (success && !input_data_view.ReadReceiver(&p_receiver))
1220         success = false;
1221       if (!success) {
1222         ReportValidationErrorForMessage(
1223             message,
1224             mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
1225             ChildProcess::Name_, 7, false);
1226         return false;
1227       }
1228       // A null |impl| means no implementation was bound.
1229       DCHECK(impl);
1230       impl->BindReceiver(
1231 std::move(p_receiver));
1232       return true;
1233     }
      .......
1259     }
1260   }
1261   return false;
1262 }
                                                                                                              

函数很简单,根据message的名称反序列化参数,然后调用ChildThreadImpl::IOThreadState的对应方法。

以上就是典型的ipcz binding 使用。 整体通信借助ipcz 通道。文章来源地址https://www.toymoban.com/news/detail-788873.html

到了这里,关于chromium通信系统-ipcz系统(十一)-mojo binding的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端(二十一)——WebSocket:实现实时双向数据传输的Web通信协议

    🤨博主:小猫娃来啦 🤨文章核心: WebSocket:实现实时双向数据传输的Web通信协议 在当今互联网时代,实时通信已成为很多应用的需求。为了满足这种需求,WebSocket协议被设计出来。WebSocket是一种基于TCP议的全双工通信协议,通过WebSocket,Web应用程序可以与服务器建立持久

    2024年02月04日
    浏览(64)
  • Hello, Mojo——首次体验Mojo语言

    官方是这样介绍Mojo语言的。 ‘’‘Mojo 是一种新的编程语言,它通过将最佳的 Python 语法与系统编程和元编程相结合,弥合了研究与生产之间的差距。 使用 Mojo,您可以编写比 C 更快的可移植代码,并与 Python 生态系统无缝互操作。’‘’ 在之前我听说这个语言之后我就立马

    2024年02月04日
    浏览(55)
  • 如何更快的烹饪出美味的MOJO系列教程?之初识MOJO

    Mojo是一种编程语言,它与Python一样易于使用,但具有C++和Rust的性能。此外,Mojo提供了利用整个Python库生态系统的能力。 Mojo 通过利用具有集成缓存、多线程和云分发技术的下一代编译器技术来实现这一壮举。此外,Mojo的自动调整和编译时元编程功能允许您编写可移植到最奇

    2024年02月07日
    浏览(48)
  • chromium 46 编译chromium老版本流程

    官网老版本获取流程:https://chromium.googlesource.com/chromium/src/+/main/docs/building_old_revisions.md 有些老项目,使用的是稍微老一点的chromium版本,为了做比较全面的对比和研究,处理官网下载历史版本外,有时,可能需要编译对应的老版本。这里以 57.0.2987.98 为例,描述 windows版本编译

    2024年02月12日
    浏览(43)
  • mojo初体验

    https://www.modular.com/get-started 与python基础语法很相似。 let定义不可变变量 var定义可变变量 下面是一个基本的函数: 请注意,上面的 add() 不会修改 x or y ,它只会读取值。事实上,正如所写的,函数无法修改它们,因为默认情况下 fn 参数是不可变的引用。 就参数约定而言,这

    2024年02月09日
    浏览(43)
  • Mojo 语言官网

    Mojo面向 AI 开发者的新型编程语言,无缝支持CPU、GPU,兼容Python,跟Python类似的语法,但是比Python快68000倍。目前Mojo仅支持Ubuntu,暂不支持Windows和Mac,可以在Mojo Playground先体验一下。 Mojo 语言官网 Mojo简易教程

    2024年02月09日
    浏览(38)
  • mojo 介绍

    注 :本文是根据官方网站翻译得来,其中做了部分修改用于理解文章字义。 Mojo被设计为Python的超集,因此许多语言功能和你可能在Python中知道的概念可以直接翻译成Mojo。例如一个 Mojo中的“Hello World”程序看起来和Python一模一样: 您还可以导入现有的 Python 包并使用它们,

    2024年02月11日
    浏览(44)
  • 解决java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter三更博客系统

    这个错误通常发生在使用JDK 9或更高版本的Java应用程序中,因为在这些版本中,JDK已经移除了JAXB默认实现的某些部分。 要解决这个问题,您可以尝试以下几个步骤: 升级您的应用程序以使用JAXB的最新实现。可以从Maven仓库或JAXB的官方网站中获取JAXB的最新版本。 1. 如果您使

    2024年02月15日
    浏览(80)
  • 全新编程语言【Mojo】诞生

    Mojo 是一种新的编程语言,它通过将最佳的 Python 语法与系统编程和元编程相结合,弥合了研究与生产之间的差距。 使用 Mojo,您可以编写比 C 更快的可移植代码,并与 Python 生态系统无缝互操作。 大牛Chris Lattner 说起 Chris Lattner,大家一定不陌生。这位编译器大神,曾经领导

    2024年02月06日
    浏览(42)
  • 一、MOJO环境部署和安装

    以Ubuntu系统为例。 安装mojo-CLI curl https://get.modular.com | MODULAR_AUTH=mut_fe303dc5ca504bc4867a1db20d897fd8 sh - 安装mojo SDK modular auth mojo modular auth install mojo 查看mojo版本号 mojo --version 输入mojo指令,进入交互编程窗口

    2024年02月01日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包