Chromium Mojo(IPC)进程通信演示 c++(3)

122版本自带的mojom通信例子channel-associated-interface 仅供学习参考:

codelabs\mojo_examples\03-channel-associated-interface-freezing

其余定义参考上一篇文章:

Chromium Mojo(IPC)进程通信演示 c++(2)-CSDN博客​​​​​​

03-mojo-browser.exe 与 03-mojo-renderer.exe进程通信完整例子。

一、目录结构:

二、03-mojo-browser.exe

codelabs\mojo_examples\03-channel-associated-interface-freezing\browser.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_pump.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/threading/thread.h"
#include "codelabs/mojo_examples/mojom/interface.mojom.h"
#include "codelabs/mojo_examples/process_bootstrapper.h"
#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_channel_proxy.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"mojo::ScopedMessagePipeHandle LaunchAndConnect() {// Under the hood, this is essentially always an OS pipe (domain socket pair,// Windows named pipe, Fuchsia channel, etc).mojo::PlatformChannel channel;mojo::OutgoingInvitation invitation;// Attach a message pipe to be extracted by the receiver. The other end of the// pipe is returned for us to use locally.mojo::ScopedMessagePipeHandle ipc_bootstrap_pipe =invitation.AttachMessagePipe("ipc_bootstrap_pipe");base::LaunchOptions options;// This is the relative path to the mock "renderer process" binary. We pass it// into `base::LaunchProcess` to run the binary in a new process.static const base::CommandLine::CharType* argv[] = {FILE_PATH_LITERAL("./03-mojo-renderer")};base::CommandLine command_line(1, argv);channel.PrepareToPassRemoteEndpoint(&options, &command_line);LOG(INFO) << "Browser: " << command_line.GetCommandLineString();base::Process child_process = base::LaunchProcess(command_line, options);channel.RemoteProcessLaunchAttempted();mojo::OutgoingInvitation::Send(std::move(invitation), child_process.Handle(),channel.TakeLocalEndpoint());return ipc_bootstrap_pipe;
}class BrowserIPCListener : public IPC::Listener {public:BrowserIPCListener(mojo::ScopedMessagePipeHandle ipc_bootstrap_pipe,scoped_refptr<base::SingleThreadTaskRunner> io_task_runner): IPC::Listener() {// This program differs from `02-associated-interface-freezing`, because// we're using channel-associated interfaces as opposed to non-channel// associated interfaces. This means we need to set up an// `IPC::ChannelProxy` in addition to the regular mojo stuff. The sequence// of events will look like so://   1.) Bootstrap the IPC channel. This is actually pretty easy. We just a//       pull a message pipe handle off of the mojo invitation we sent to//       the renderer process earlier, and feed that pipe handle into the//       IPC::ChannelProxy. From there, we can start requesting remote//       associated interfaces directly from the IPC channel.//   2.) Requesting a remote channel-associated interface from the//       IPC::Channel mojo connection, for interface//       `codelabs::mojom::ObjectA`//   3.) Do the same thing as (2) but for `codelabs::mojom::ObjectB`. Both//       of our `ObjectA` and `ObjectB` connections are channel-associated,//       however the remote "renderer" process will bind the backing//       mojo::AssociatedReceiver for each of these to different TaskQueues.////       We first send a message to `ObjectA`, whose backing//       mojo::AssociatedReceiver is bound to a TaskQueue that is initially//       frozen////       We then send a message to `ObjectB`, whose backing//       mojo::AssociatedReceiver is bound to a normal unfrozen TaskQueue.////       From this we see two results://         - The message for `ObjectA` is not delayed, despite its//           AssociatedReceiver being bound to a frozen TaskQueue. This is//           because we cannot delay channel-associated message from being//           delivered due to legacy IPC deadlock reasons//         - If you then comment out the part of the renderer code that//           binds the `ObjectA` interface (so that you prevent it from ever//           being bound to an implementation), you then observe that the//           `ObjectB` message is not blocked at all on the `ObjectA`//           message, for the same reasons above.// 1.) Bootstrap the IPC Channel.std::unique_ptr<IPC::ChannelFactory> channel_factory =IPC::ChannelMojo::CreateServerFactory(std::move(ipc_bootstrap_pipe), io_task_runner,base::SingleThreadTaskRunner::GetCurrentDefault());channel_proxy_ = IPC::ChannelProxy::Create(std::move(channel_factory), this, /*ipc_task_runner=*/io_task_runner,/*listener_task_runner=*/base::SingleThreadTaskRunner::GetCurrentDefault());// 2.) Bind and send an IPC to ObjectA.mojo::AssociatedRemote<codelabs::mojom::ObjectA> remote_a;channel_proxy_->GetRemoteAssociatedInterface(&remote_a);remote_a->DoA();// 3.) Bind and send an IPC to ObjectB.mojo::AssociatedRemote<codelabs::mojom::ObjectB> remote_b;channel_proxy_->GetRemoteAssociatedInterface(&remote_b);remote_b->DoB();}// IPC::Listener implementation.bool OnMessageReceived(const IPC::Message& msg) override {CHECK(false) << "The browser should not receive messages";return false;}void OnAssociatedInterfaceRequest(const std::string& interface_name,mojo::ScopedInterfaceEndpointHandle handle) override {CHECK(false)<< "The browser should not receive associated interface requests";}private:std::unique_ptr<IPC::ChannelProxy> channel_proxy_;
};int main(int argc, char** argv) {LOG(INFO) << "Browser process starting up";base::CommandLine::Init(argc, argv);ProcessBootstrapper bootstrapper;// The IO thread that the `BrowserIPCListener` ChannelProxy listens for// messages on *must* be different than the main thread, so in this example// (and in the corresponding "renderer.cc") we initialize the main thread with// a "DEFAULT" (i.e., non-IO-capable) main thread. This will automatically// give us a separate dedicated IO thread for Mojo and the IPC infrastructure// to use.bootstrapper.InitMainThread(base::MessagePumpType::DEFAULT);bootstrapper.InitMojo(/*as_browser_process=*/true);mojo::ScopedMessagePipeHandle handle = LaunchAndConnect();// Create a new `BrowserIPCListener` to sponsor communication coming from the// "browser" process. The rest of the program will execute there.std::unique_ptr<BrowserIPCListener> browser_ipc_listener =std::make_unique<BrowserIPCListener>(std::move(handle),bootstrapper.io_task_runner);base::RunLoop run_loop;// Delay shutdown of the browser process for visual effects, as well as to// ensure the browser process doesn't die while the IPC message is still being// sent to the target process asynchronously, which would prevent its// delivery. This delay is an arbitrary 5 seconds, which just needs to be// longer than the renderer's 3 seconds, which is used to show visually via// logging, how the ordering of IPCs can be effected by a frozen task queue// that gets unfrozen 3 seconds later.base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(FROM_HERE,base::BindOnce([](base::OnceClosure quit_closure) {LOG(INFO) << "'Browser process' shutting down";std::move(quit_closure).Run();},run_loop.QuitClosure()),base::Seconds(5));run_loop.Run();return 0;
}

三、03-mojo-renderer.exe

codelabs\mojo_examples\03-channel-associated-interface-freezing\renderer.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.#include <memory>#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/task/sequence_manager/task_queue.h"
#include "codelabs/mojo_examples/mojo_impls.h"
#include "codelabs/mojo_examples/mojom/interface.mojom.h"
#include "codelabs/mojo_examples/process_bootstrapper.h"
#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_sync_channel.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"static ObjectAImpl g_object_a;
static ObjectBImpl g_object_b;class CustomTaskQueue : public base::RefCounted<CustomTaskQueue> {public:CustomTaskQueue(base::sequence_manager::SequenceManager& sequence_manager,const base::sequence_manager::TaskQueue::Spec& spec): task_queue_(sequence_manager.CreateTaskQueue(spec)),voter_(task_queue_->CreateQueueEnabledVoter()) {}void FreezeTaskQueue() { voter_->SetVoteToEnable(false); }void UnfreezeTaskQueue() {LOG(INFO) << "Unfreezing the task queue that `ObjectAImpl` is bound to.";voter_->SetVoteToEnable(true);}const scoped_refptr<base::SingleThreadTaskRunner>& task_runner() const {return task_queue_->task_runner();}private:~CustomTaskQueue() = default;friend class base::RefCounted<CustomTaskQueue>;base::sequence_manager::TaskQueue::Handle task_queue_;// Used to enable/disable the underlying `TaskQueueImpl`.std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> voter_;
};class RendererIPCListener : public IPC::Listener {public:RendererIPCListener(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,scoped_refptr<base::SingleThreadTaskRunner> initially_frozen_task_runner): initially_frozen_task_runner_(initially_frozen_task_runner) {// The sequence of events we'll need to perform are the following://   1.) Create the ChannelProxy (specifically a SyncChannel) for the//       receiving end of the IPC communication.//   2.) Accept the incoming mojo invitation. From the invitation, we//       extract a message pipe that we will feed directly into the//       `IPC::ChannelProxy` to initialize it. This bootstraps the//       bidirectional IPC channel between browser <=> renderer.// 1.) Create a new IPC::ChannelProxy.channel_proxy_ = IPC::SyncChannel::Create(this, io_task_runner, base::SingleThreadTaskRunner::GetCurrentDefault(),&shutdown_event_);// 2.) Accept the mojo invitation.mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(*base::CommandLine::ForCurrentProcess()));mojo::ScopedMessagePipeHandle ipc_bootstrap_pipe =invitation.ExtractMessagePipe("ipc_bootstrap_pipe");// Get ready to receive the invitation from the browser process, which bears// a message pipe represented by `ipc_bootstrap_pipe`.channel_proxy_->Init(IPC::ChannelMojo::CreateClientFactory(std::move(ipc_bootstrap_pipe), /*ipc_task_runner=*/io_task_runner,/*proxy_task_runner=*/base::SingleThreadTaskRunner::GetCurrentDefault()),/*create_pipe_now=*/true);}private:// IPC::Listener implementation.bool OnMessageReceived(const IPC::Message& msg) override {LOG(WARNING) << "The renderer received a message";return true;}void OnAssociatedInterfaceRequest(const std::string& interface_name,mojo::ScopedInterfaceEndpointHandle handle) override {std::string tmp_name = interface_name;LOG(WARNING) << "The renderer received an associated interface request for "<< tmp_name.c_str();if (interface_name == "codelabs.mojom.ObjectA") {// Amazingly enough, if you comment out all of this code, which causes the// `ObjectA` interface to not get bound and therefore the `DoA()` message// to never be delivered, the `DoB()` message still gets delivered and// invoked on `ObjectB`. This is because channel-associated interface// messages are dispatched very differently than non-channel-associated// ones, because we can't block at all.mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectA> pending_a(std::move(handle));g_object_a.BindToFrozenTaskRunner(std::move(pending_a), std::move(initially_frozen_task_runner_));} else if (interface_name == "codelabs.mojom.ObjectB") {mojo::PendingAssociatedReceiver<codelabs::mojom::ObjectB> pending_b(std::move(handle));g_object_b.Bind(std::move(pending_b));}}std::unique_ptr<IPC::SyncChannel> channel_proxy_;scoped_refptr<base::SingleThreadTaskRunner> initially_frozen_tq_;base::WaitableEvent shutdown_event_{base::WaitableEvent::ResetPolicy::MANUAL,base::WaitableEvent::InitialState::NOT_SIGNALED};scoped_refptr<base::SingleThreadTaskRunner> initially_frozen_task_runner_;
};int main(int argc, char** argv) {base::AtExitManager exit_manager;base::CommandLine::Init(argc, argv);LOG(INFO) << "Renderer: "<< base::CommandLine::ForCurrentProcess()->GetCommandLineString();ProcessBootstrapper bootstrapper;// See the documentation above the corresponding "browser.cc".bootstrapper.InitMainThread(base::MessagePumpType::DEFAULT);bootstrapper.InitMojo(/*as_browser_process=*/false);// This is the task queue that `ObjectAImpl`'s receiver will be bound to. We// freeze it to demonstrate that channel-associated interfaces bound to frozen// queues *still* have their messages delivered.scoped_refptr<CustomTaskQueue> initially_frozen_tq =base::MakeRefCounted<CustomTaskQueue>(*bootstrapper.sequence_manager.get(),base::sequence_manager::TaskQueue::Spec(base::sequence_manager::QueueName::TEST_TQ));initially_frozen_tq->FreezeTaskQueue();// The rest of the magic happens in this object.std::unique_ptr<RendererIPCListener> renderer_ipc_listener =std::make_unique<RendererIPCListener>(/*io_task_runner=*/bootstrapper.io_task_runner,initially_frozen_tq->task_runner());// Post a task for 3 seconds from now that will unfreeze the TaskRunner that// the `codelabs::mojom::ObjectA` implementation is bound to. This would// normally block all messages from going to their corresponding// implementations (i.e., messages bound for ObjectA would be blocked, and// necessarily subsequent messages bound for ObjectB would *also* be blocked),// however since the associated interfaces here are specifically// *channel*-associated, we do not support blocking messages, so they're all// delivered immediately.base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(FROM_HERE,base::BindOnce([](scoped_refptr<CustomTaskQueue> initially_frozen_tq) {LOG(INFO) << "Unfreezing frozen TaskRunner";initially_frozen_tq->UnfreezeTaskQueue();},initially_frozen_tq),base::Seconds(3));// This task is posted first, but will not run until the task runner is// unfrozen in ~3 seconds.initially_frozen_tq->task_runner()->PostTask(FROM_HERE, base::BindOnce([]() {LOG(WARNING) << "Renderer: This is the first task posted to the frozen ""TaskRunner. It shouldn't run within the first 2 ""seconds of the program";}));base::RunLoop run_loop;run_loop.Run();return 0;
}

四、编译

  1、gn gen out/debug

  2、 ninja -C out/debug 03-mojo-browser

      生成03-mojo-browser.exe

 3、ninja -C out/debug 03-mojo-renderer

       生成03-mojo-renderer.exe

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/11598.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用SparkSQL在hive中使用Spark的引擎计算

在hive中&#xff0c;由于hive自带的计算引擎计算比较慢&#xff0c;这个时候可以使用spark替换hive的计算引擎&#xff0c;可以增加hive的计算速度。 在替换之前&#xff0c;首先虚拟机上要有spark的集群模式&#xff0c;spark 的yarn集群模式&#xff0c;需要hdfs&#xff0…

MySQL数据库: 初始MySQL +Navicat (学习笔记)

目录 一&#xff0c;MySQL数据库基本概念 1&#xff0c;数据 2&#xff0c;数据库 3&#xff0c;数据库管理系统 4&#xff0c;数据库应用程序 5&#xff0c;数据库管理员 6&#xff0c;最终用户 7&#xff0c;数据库系统 二&#xff0c;MySQL数据库的分类 1&#xf…

22.04Ubuntu---ROS2创建python节点

创建工作空间 mkdir -p 02_ros_ws/src 然后cd到该目录 创建功能包 在这条命令里&#xff0c;tom就是你的功能包 ros2 pkg create tom --build-type ament_python --dependencies rclpy 可以看到tom功能包已经被创建成功了。 使用tree命令&#xff0c;得到如下文件结构 此时…

多模态大模型技术方向和应用场景

多模态大模型&#xff08;Multimodal Large Language Models&#xff0c;MLLM&#xff09;是一种结合了大型语言模型&#xff08;LLM&#xff09;和大型视觉模型&#xff08;LVM&#xff09;的深度学习模型&#xff0c;它们能够处理和理解多种类型的数据&#xff0c;如文本、图…

力扣 LeetCode 977. 有序数组的平方

解题思路&#xff1a; 方法一&#xff1a;先平方再快排 方法二&#xff1a;双指针 因为可能有负数&#xff0c;所以对于一个数组 [ -5 , -3 , 0 , 2 , 4 ] 可以从两边向内靠拢&#xff0c;最大值一定出现在两端 设置指针 i 和指针 j 分别从左右两边靠拢 因为要从小到大排序…

程序员必备的几款爬虫软件,搞定复杂数据抓取任务

作为一名数据工程师&#xff0c;三天两头要采集数据&#xff0c;用过十几种爬虫软件&#xff0c;也用过Python爬虫库&#xff0c;还是建议新手使用现成的软件比较方便。 这里推荐3款不错的自动化爬虫工具&#xff0c;八爪鱼、亮数据、Web Scraper 1. 八爪鱼爬虫 八爪鱼爬虫是一…

008_SSH_Sqlserverl图书管理系统(学生注册 借书 还书)_lwplus87(免费送)

目 录 Abstract IV 第1章 概述... 1 1.1 课题背景... 1 1.2 课题意义... 1 1.3 文献综述... 2 1.3.1 技术综述... 2 1.4 总体设计原则... 2 第2章 系统分析... 4 2.1 系统的需求分析... 4 2.2 业务流程分析... 5 2.2.1 系统管理员业务流程分析... 5 2.3 数据流程分析... 7 2…

EM是什么?如何修复EM violation?

芯冰乐知识星球入口:芯冰乐 EM就electric-migration,即电迁移。电子在金属导体内迁移时,会与金属原子发生碰撞。时间久了,金属原子便会往电子方向进行移动,导致金属导体发生断裂的现象,我们称之为电迁移现象。 如果金属导体内的电流越大,意味着移动的电子数也就越多。…

SQL面试题——连续出现次数

SQL面试题——连续出现次数 其实前面关于连续问题&#xff0c;我们遇到过&#xff0c;就是最大连续登陆天数&#xff0c;或者是连续登陆天数的计算&#xff0c;可以参考我们之前的文章 SQL面试题——最大连续登陆问题 最大连续登陆问题 最大连续登陆问题的难点在于如何判断…

【LLM】3:从零开始训练大语言模型(预训练、微调、RLHF)

一、 大语言模型的训练过程 预训练阶段&#xff1a;PT&#xff08;Pre training&#xff09;。使用公开数据经过预训练得到预训练模型&#xff0c;预训练模型具备语言的初步理解&#xff1b;训练周期比较长&#xff1b;微调阶段1&#xff1a;SFT&#xff08;指令微调/有监督微调…

腾讯云双11优惠大揭秘:省钱攻略不容错过!

文章目录 1 云服务来袭2 新手大礼包3 轻量应用服务器来袭4 腾讯云福利来袭5 福利代金券来袭 1 云服务来袭 云服务器能够灵活地提供计算和存储资源&#xff0c;帮助用户高效地应对信息技术需求&#xff0c;并保障数据的安全性。各大云服务商也因此纷纷推出多样化的优惠活动&…

皮卡超级壁纸 1.4.1 | 解锁会员版的全景壁纸、动态壁纸和超级壁纸

皮卡超级壁纸是一款提供海量壁纸的应用&#xff0c;不仅包含静态的精美壁纸&#xff0c;还提供了独特的超级壁纸。这些超级壁纸不仅仅是动态效果&#xff0c;还能自动匹配用户的手机UI&#xff0c;提供更加个性化的体验。解锁会员版后&#xff0c;用户可以享受更多高级功能和壁…

“绽放艺术风采、激发强国力量” 海南省第十一届中小学生艺术展演活动圆满开展

2024年11月1日&#xff0c;由省教育厅主办、琼台师范学院承办的海南省第十一届中小学生艺术展演省级展演活动在海口正式拉开帷幕。来自全省各市县、省属学校等共计4000余名师生参加本届中小学生艺术展演现场展演活动。 本届展演活动以“绽放艺术风采、激发强国力量”为主题&…

如何挑选靠谱的IP代理池?

嘿&#xff0c;寻觅一个靠谱的IP代理池就好比找到一双合脚的跑鞋&#xff0c;舒适性和耐用性缺一不可。IP代理池同样要支撑您在网络世界中“跑”得更快更远。所以&#xff0c;别急&#xff0c;我们来看看有哪些小妙招&#xff0c;教您挑选出最合适的IP代理池吧&#xff01; 看…

2024/11/10周报

文章目录 摘要GCNCNNGA混合模型预测进水水质代码运行结果 文献阅读题目研究背景与意义研究方法数据采集与预处理GCN–CNNGA混合深度学习框架的构建 模型优化与实验邻接矩阵的构建与效果分析模型预测效果对比多步预测性能 模型优势与应用前景精度提升与处理效率运营决策的优化支…

公司内部最好用的开源导航网站(EasyNav)

公司导航门户 一个现代化的企业内部导航门户系统&#xff0c;用于集中管理和展示公司各类系统和资源的链接。 项目地址&#xff1a;https://github.com/starslink/EasyNav体验地址&#xff1a;www.easynav.icu/ 功能特点 &#x1f510; 用户认证与授权邮箱注册与验证 JWT t…

pulsar源码--3-官方文档杂技

消息队列中间件会保存消息&#xff0c;直到收到消费者消费成功并确认&#xff0c;在此之后消息便可以删除&#xff0c;不过什么时候删除&#xff0c;由中间件自己决定 ack消息会一直储存&#xff0c;直到现有的所有订阅都确认了这条消息&#xff0c;在此之后如果要继续保存则需…

为什么一些工业厂房的配电箱和供电线路要安装ALP?

1、什么是ALP&#xff1f; ALP 低压线路保护装置是一种智能型电气保护设备&#xff0c;适用于额定电压至 AC660V、额定电流至 AC400A、额定频率为 50/60Hz 的低压系统。集保护、测量、控制、总线通讯为一体&#xff0c;是低压馈线终端的智能化综合装置。 2、功能特点 ①能够…

如何让 AI 更懂你:提示词的秘密

目录 前言常见概念大语言模型&#xff08;Large Language Model&#xff09;大模型输入常见参数提示词工程的限制 战略思想效果评测复杂任务拆解提示词结构化加示例加要求加维度 提示词框架 前言 小册推荐&#xff1a;https://juejin.cn/book/7399064580883742774 评估响应内…

特征值分解原理和实战

特征值分解&#xff08;Eigenvalue Decomposition&#xff09;是线性代数中的一种重要技术&#xff0c;用于分析矩阵的内在属性。这种分解方法主要适用于方阵&#xff08;即行数和列数相等的矩阵&#xff09;&#xff0c;用于将矩阵分解为其特征向量和特征值。 基本原理 假设 …