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

   网上搜索关于mojo教程 多数都是理论 加上翻译谷歌mojo文档的,但是如何自定义两个进程使用mojo通信呢?看下面的完整例子介绍:(本人也是参考谷歌代码例子改编而成)

本文演示了client.exe和service.exe 通过mojo::IncomingInvitation模式进行通信使用例子。

废话不多说直接上代码:

一、目录结构如下图:

按照如图所示目录结构添加文件即可。 

二、定义sample.mojom接口

1、demo\logger\public\mojom\sample.mojom

module sample.mojom;interface Logger {Log(string message);GetTail() => (string message);
};

2、demo\logger\public\mojom\BUILD.gn

import("//mojo/public/tools/bindings/mojom.gni")mojom("mojom") {sources = ["sample.mojom",]
}

3、gn gen out/debug 自动生成代码如下:

out\Debug\gen\demo\logger\public\mojom\sample.mojom.h

out\Debug\gen\demo\logger\public\mojom\sample.mojom.cc 

其他更多参考out\Debug\gen\demo\logger\目录下

三、client.exe端代码: 

1、demo\client\client.cc  //client.exe main函数实现文件:

#include<iostream>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "demo/logger/public/mojom/sample.mojom.h"
#include "demo/client/logger_test.h"
#include "demo/process_bootstrapper_helper.h"
#include "mojo/core/embedder/configuration.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. We choose the arbitrary name "pipe"// here, which is the same name that the receiver will have to use when// plucking this pipe off of the invitation it receives to join our process// network.mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe("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("./service")};base::CommandLine command_line(1, argv);// Delegating to Mojo to "prepare" the command line will append the// `--mojo-platform-channel-handle=N` command line argument, so that the// renderer knows which file descriptor name to recover, in order to establish// the primordial connection with this process. We log the full command line// next, to show what mojo information the renderer will be initiated with.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 pipe;
}logger_test *g_logger_test = nullptr;void CreateProcessRemote(mojo::ScopedMessagePipeHandle pipe,const std::string& msg) {mojo::PendingRemote<sample::mojom::Logger> pending_remote(std::move(pipe),0u);mojo::Remote<sample::mojom::Logger> remote(std::move(pending_remote));g_logger_test = new logger_test(std::move(remote));LOG(INFO) << "Browser invoking SayHello() on remote pointing to renderer";g_logger_test->sendLoggerMsg(msg);g_logger_test->sendLoggerExt();
}int main(int argc, const char* argv[]) {base::AtExitManager at_exit_manager;base::CommandLine::Init(argc, argv);ProcessBootstrapperHelp bootstrapper;bootstrapper.InitMainThread(base::MessagePumpType::IO);bootstrapper.InitMojo(/*as_browser_process=*/true);mojo::ScopedMessagePipeHandle pipe = LaunchAndConnect();std::string msg("jd test");base::SequencedTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, base::BindOnce(&CreateProcessRemote, std::move(pipe),msg));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.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(2));run_loop.Run();delete g_logger_test;g_logger_test = nullptr;return 0;
}

2、demo\client\logger_test.cc

#include "demo/client/logger_test.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <iostream>
#include "base/functional/bind.h"logger_test::logger_test(mojo::Remote<sample::mojom::Logger> rc): logger_client_(std::move(rc)) {}logger_test::~logger_test() {std::cout << "~logger_test()\n";
}void logger_test::sendLoggerMsg(const std::string& msg) {logger_client_->Log(msg);
}void logger_test::GetTailCallbackTest(const std::string& msg){LOG(ERROR) << "GetTail callback " << msg;}
void logger_test::sendLoggerExt(){logger_client_->GetTail(base::BindOnce(&logger_test::GetTailCallbackTest,base::Unretained(this)));
}

3、demo\client\logger_test.h


#ifndef CHROME_BROWSER_LOGGER_TEST_H_
#define CHROME_BROWSER_LOGGER_TEST_H_
#include <string>
#include <vector>
#include "base/logging.h"
#include "demo/logger/public/mojom/sample.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"class logger_test {public:logger_test(mojo::Remote<sample::mojom::Logger> rc);~logger_test();void sendLoggerMsg(const std::string& msg);void sendLoggerExt();private:void GetTailCallbackTest(const std::string& msg);/* data */mojo::Remote<sample::mojom::Logger> logger_client_;
};#endif  // CHROME_BROWSER_LOGGER_TEST_H_

四、service.exe端代码: 

1、demo\service\service.cc  //service.exe main函数实现文件:

#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <iostream>#include <initializer_list>
#include <memory>
#include <string>
#include <tuple>
#include <vector>#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "demo/process_bootstrapper_helper.h"
#include "demo/service/LoggerImpl.h"
#include "mojo/core/embedder/configuration.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.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"LoggerImpl* g_process_impl = nullptr;void BindProcessImpl(mojo::ScopedMessagePipeHandle pipe) {// Create a receivermojo::PendingReceiver<sample::mojom::Logger> pending_receiver(std::move(pipe));g_process_impl = new LoggerImpl(std::move(pending_receiver));
}int main(int argc, const char* argv[]) {base::AtExitManager at_exit_manager;base::CommandLine::Init(argc, argv);const base::CommandLine& command_line =*base::CommandLine::ForCurrentProcess();std::wcout << command_line.GetCommandLineString().c_str()<<"\n";ProcessBootstrapperHelp bootstrapper;bootstrapper.InitMainThread(base::MessagePumpType::IO);bootstrapper.InitMojo(/*as_browser_process=*/false);// Accept an invitation.//// `RecoverPassedEndpointFromCommandLine()` is what makes use of the mojo// platform channel handle that gets printed in the above `LOG()`; this is the// file descriptor of the first connection that this process shares with the// browser.mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(*base::CommandLine::ForCurrentProcess()));// Extract one end of the first pipe by the name that the browser process// added this pipe to the invitation by.mojo::ScopedMessagePipeHandle pipe = invitation.ExtractMessagePipe("pipe");base::RunLoop run_loop;base::SequencedTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE, base::BindOnce(&BindProcessImpl, std::move(pipe)));run_loop.Run();std::cout << "service\n";return 0;
}

LoggerImpl.h 和LoggerImpl.cc 是sample::mojom::Logger 实现类:

2、demo\service\LoggerImpl.h

#ifndef CHROME_BROWSER_LOGGERIMPL_H_
#define CHROME_BROWSER_LOGGERIMPL_H_#include <string>
#include <vector>
#include "base/logging.h"
#include "demo/logger/public/mojom/sample.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"class LoggerImpl : public sample::mojom::Logger {public:// NOTE: A common pattern for interface implementations which have one// instance per client is to take a PendingReceiver in the constructor.explicit LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> pending_receiver);~LoggerImpl() override;// sample::mojom::Logger:void Log(const std::string& message) override;void GetTail(GetTailCallback callback) override;void OnError();private:mojo::Receiver<sample::mojom::Logger> receiver_;std::vector<std::string> lines_;LoggerImpl(const LoggerImpl&) = delete;LoggerImpl& operator=(const LoggerImpl&) = delete;
};#endif  // CHROME_BROWSER_LOGGERIMPL_H_

3、demo\service\LoggerImpl.cc


#include "demo/service/LoggerImpl.h"
#include "base/functional/bind.h"LoggerImpl::LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> pending_receiver): receiver_(this, std::move(pending_receiver)) {// receiver_.Bind(std::move(pending_receiver));receiver_.set_disconnect_handler(base::BindOnce(&LoggerImpl::OnError, base::Unretained(this)));
}LoggerImpl::~LoggerImpl() {}// sample::mojom::Logger:
void LoggerImpl::Log(const std::string& message) {LOG(ERROR) << "[Logger] " << message;lines_.push_back(message);
}void LoggerImpl::GetTail(GetTailCallback callback) {std::move(callback).Run(lines_.back());
}void LoggerImpl::OnError() {LOG(ERROR) << "Client disconnected! Purging log lines.";lines_.clear();
}

五、初始化mojo和线程辅助类: 

demo\process_bootstrapper_helper.h

// 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.#ifndef CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_HELPER_H_
#define CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_HELPER_H_#include "base/message_loop/message_pump.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/threading/thread.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"class ProcessBootstrapperHelp {public:ProcessBootstrapperHelp();~ProcessBootstrapperHelp();// This sets up the main thread with a message pump of `type`, and optionally// a dedicated IO thread if `type` is *not* `base::MessagePumpType::IO`.void InitMainThread(base::MessagePumpType type) {// Creates a sequence manager bound to the main thread with a message pump// of some specified type. The message pump determines exactly what the// event loop on its thread is capable of (i.e., what *kind* of messages it// can "pump"). For example, a `DEFAULT` message pump is capable of// processing simple events, like async timers and posted tasks. The `IO`// message pump type — which is used in every example in this codelab — is// capable of asynchronously processing IO over IPC primitives like file// descriptors, used by Mojo. A thread with *that* kind of message pump is// required for any process using Mojo for IPC.std::unique_ptr<base::MessagePump> pump = base::MessagePump::Create(type);sequence_manager =base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump(std::move(pump),base::sequence_manager::SequenceManager::Settings::Builder().SetMessagePumpType(type).Build());default_tq = std::make_unique<base::sequence_manager::TaskQueue::Handle>(sequence_manager->CreateTaskQueue(base::sequence_manager::TaskQueue::Spec(base::sequence_manager::QueueName::DEFAULT_TQ)));sequence_manager->SetDefaultTaskRunner((*default_tq)->task_runner());if (type == base::MessagePumpType::DEFAULT) {InitDedicatedIOThread();}}// Must be called after `InitMainThread()`.void InitMojo(bool as_browser_process) {CHECK(default_tq) << "Must call `InitMainThread()` before `InitMojo()`";// Basic Mojo initialization for a new process.mojo::core::Configuration config;// For mojo, one process must be the broker process which is responsible for// trusted cross-process introductions etc. Traditionally this is the// "browser" process.config.is_broker_process = as_browser_process;mojo::core::Init(config);// The effects of `ScopedIPCSupport` are mostly irrelevant for our simple// examples, but this class is used to determine how the IPC system shuts// down. The two shutdown options are "CLEAN" and "FAST", and each of these// may determine how other processes behave if *this* process has a message// pipe that is in the middle of proxying messages to another process where// the other end of the message pipe lives.//// In real Chrome, both the browser and renderer processes can safely use// `FAST` mode, because the side effects of quickly terminating the IPC// system in the middle of cross-process IPC message proxying is not// important. See this class's documentation for more information on// shutdown.//// We initialize `ipc_support` with a task runner for whatever thread should// be the IO thread. This means preferring `io_task_runner` when it is// non-null, and the default task runner otherwise.mojo::core::ScopedIPCSupport ipc_support(io_task_runner ? io_task_runner : (*default_tq)->task_runner(),mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST);}std::unique_ptr<base::sequence_manager::TaskQueue::Handle> default_tq;std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager;scoped_refptr<base::SingleThreadTaskRunner> io_task_runner;private:// Note that you cannot call this if you've ever called// `InitMainThread(base::MessagePumpType::IO)` since that means the main// thread *itself* the IO thread.void InitDedicatedIOThread() {io_thread_ = std::make_unique<base::Thread>("ipc!");io_thread_->StartWithOptions(base::Thread::Options(base::MessagePumpType::IO, 0));io_task_runner = io_thread_->task_runner();}std::unique_ptr<base::Thread> io_thread_;
};ProcessBootstrapperHelp::ProcessBootstrapperHelp() = default;
ProcessBootstrapperHelp::~ProcessBootstrapperHelp() = default;#endif  // CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_HELPER_H_

六、添加demo\build.gn文件:

   1、  dem\BUILD.gn

# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.import("//build/config/compiler/compiler.gni")group("jdcode_mojo_examples") {testonly = trueif (is_win) {deps = [":client",":service",]}
}executable("client") {sources = ["client/client.cc","client/logger_test.cc","client/logger_test.h","process_bootstrapper_helper.h",]if (is_win) {ldflags = [ "/LARGEADDRESSAWARE" ]}deps = ["//base","//build/win:default_exe_manifest","//demo/logger/public/mojom","//ipc","//mojo/core/embedder","//mojo/public/cpp/platform","//mojo/public/mojom/base",]
}executable("service") {sources = ["service/service.cc","service/LoggerImpl.h","service/LoggerImpl.cc","process_bootstrapper_helper.h",]if (is_win) {ldflags = [ "/LARGEADDRESSAWARE" ]}deps = ["//base","//build/win:default_exe_manifest","//demo/logger/public/mojom","//ipc","//mojo/core/embedder","//mojo/public/cpp/platform","//mojo/public/mojom/base",]
}

2、src\BUILD.gn 追加如下:

    if (is_win) {deps += ["//demo/logger/public/mojom","//demo:jdcode_mojo_examples",]}

七、开始编译和调试:

1、gn gen out/debug

   自动生成mojo文件:   

2、ninja -C out/debug client

编译client.exe

3、ninja -C out/debug service

编译service.exe

 4、最终生成文件如图:

八、看下调试堆栈效果: 

  8.1)、 client.exe主要流程:

1、初始化线程和mojo // mojo::core::Init(config);

  ProcessBootstrapperHelp bootstrapper;

  bootstrapper.InitMainThread(base::MessagePumpType::IO);

  bootstrapper.InitMojo(/*as_browser_process=*/true); 

2、LaunchAndConnect();

 2.1)、mojo::OutgoingInvitation建立并且启动service.exe[通过base::LaunchProcess],

2.2)将./service --mojo-platform-channel-handle=508传递给service.exe

3、CreateProcessRemote调用Log和GetTail接口函数

8.2)、service.exe主要流程:

1、初始化线程和mojo // mojo::core::Init(config);

  ProcessBootstrapperHelp bootstrapper;

  bootstrapper.InitMainThread(base::MessagePumpType::IO);

  bootstrapper.InitMojo(/*as_browser_process=*/false);

2、与client.exe建立链接:

  mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(

      mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(

          *base::CommandLine::ForCurrentProcess()));

  // Extract one end of the first pipe by the name that the browser process

  // added this pipe to the invitation by.

  mojo::ScopedMessagePipeHandle pipe = invitation.ExtractMessagePipe("pipe");

3、BindProcessImpl(mojo::ScopedMessagePipeHandle pipe)处理客户端client.exe发出的函数请求Log和GetTail

8.3)、看下最终效果图:

总结: 

本文演示了通过mojo::IncomingInvitation进行通信的完整例子,仅供参考,mojo基础和原理参考官网介绍。

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

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

相关文章

Late Chunking×Milvus:如何提高RAG准确率

01. 背景 在RAG应用开发中&#xff0c;第一步就是对于文档进行chunking&#xff08;分块&#xff09;&#xff0c;高效的文档分块&#xff0c;可以有效的提高后续的召回内容的准确性。而对于如何高效的分块是个讨论的热点&#xff0c;有诸如固定大小分块&#xff0c;随机大小分…

收藏!python初学者必会,面向对象编程中的对象概念

在Python的编程世界中,“对象”这一概念是面向对象编程&#xff08;OOP&#xff09;的核心组成部分.理解对象的特性和使用方式,对于写出优雅以及可维护的代码至关重要.在本篇教程中,我们将探讨对象的基本概念,通过案例让你更好地掌握如何在实际代码中应用这些知识. 什么是对象…

《TCP/IP网络编程》学习笔记 | Chapter 6:基于UDP的服务器端/客户端

《TCP/IP网络编程》学习笔记 | Chapter 6&#xff1a;基于UDP的服务器端/客户端 《TCP/IP网络编程》学习笔记 | Chapter 6&#xff1a;基于UDP的服务器端/客户端理解UDPUDP套接字的特点UDP内部工作原理UDP的高效使用 《TCP/IP网络编程》学习笔记 | Chapter 6&#xff1a;基于UD…

前段(vue)

目录 跨域是什么&#xff1f; SprinBoot跨域的三种解决方法 JavaScript 有 8 种数据类型&#xff0c; 金额的用什么类型。 前段 区别 JQuery使用$.ajax()实现异步请求 Vue 父子组件间的三种通信方式 Vue2 和 Vue3 存在多方面的区别。 跨域是什么&#xff1f; 跨域是指…

mysql-B+Treel(一)

介绍 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的RDBMS (Relational Database Management System&#xff0c;关系…

HarmonyOS NEXT 应用开发实战(十、从零设计一款个人中心页面详细示例)

随着HarmonyOS的不断发展&#xff0c;越来越多的开发者开始关注这个平台上的应用开发。本篇文章将详细讲解如何从零开始设计一款个人中心页&#xff0c;并在代码中实现其相关功能。 1. 项目结构设计 首先&#xff0c;我们需要设计一个合理的项目结构。我们将个人中心页面分为几…

网购选择困难症怎么破?别忘了你的这位“帮手”

每年双十一对不少人来说&#xff0c;既是购物剁手狂欢节&#xff0c;也是货比三家纠结得不行的选择困难症复发期。而现在&#xff0c;Pura 70 能够帮助我们解决不够了解商品、选择困难症等问题啦。 小艺圈选&#xff0c;圈出你感兴趣的商品&#xff0c;快速货比三家 利用指关…

bug日常记录responded with a status of 413 (Request Entity Too Large)

在本地开发没有出现这个问题&#xff0c;后面部署到服务器上时&#xff0c;开始报错&#xff0c;在网上查找资料发现是nginx的配置大小不够&#xff0c;在nginx的配置条件加上了&#xff1a; client_max_body_size 10m 然后重启nginx&#xff0c;发现这个还是不行&#xff0c…

SAP Business One:中小企业数字化转型的加速器

在竞争日益激烈的市场环境中&#xff0c;中小企业要实现稳健发展&#xff0c;就必须注重提升自身的管理效能与运营效率。SAP Business One&#xff08;简称SAP B1&#xff09;作为一款专为中小企业量身定制的企业资源规划&#xff08;ERP&#xff09;解决方案&#xff0c;凭借其…

从 PyQt5 窗口闪退问题看 Python 垃圾回收与消息机制

前言 此篇文章源于知乎上的一个问题&#xff0c;使用 PyQt5 编写 GUI 程序时&#xff0c;新创建的界面会闪退&#xff0c;本篇文章仅作记录以防以后忘记。 问题代码 import sysfrom PyQt5.QtWidgets import QApplication, QMainWindow, QPushButtonclass Main(QMainWindow):d…

java两个线程的通信/指令重排

目录 1.线程通信 2.指令重排 1.线程通信 前段时间面试笔试题&#xff0c;手写两个线程之间的通信。 问题回顾&#xff1a; 一个生产者&#xff0c;一个消费者&#xff0c;一个桌子媒介。两个线程分别是消费者和生产者。流程是生产者生产一个件商品&#xff0c;通知消费者消…

建立用邻接矩阵表示的无向图

建立用邻接矩阵表示的无向图 #include<stdio.h> #define NUM 100 typedef struct {char vexs[NUM];int edges[NUM][NUM];int n,e; }MGraph; void CreateMGraph(MGraph *G) {int i,j,k;printf("请输入顶点数和边数:");scanf("%d,%d",&G->n,&a…

大模型微调技术 --> LoRA 系列之 AdaLoRA

AdaLoRA 1.摘要 之前的微调方法(如低秩更新)通常将增量更新的预算均匀地分布在所有预训练的权重矩阵上&#xff0c;并且忽略了不同权重参数的不同重要性。结果&#xff0c;微调结果不是最优的。 为了弥补这一差距&#xff0c;我们提出了AdaLoRA&#xff0c;它根据权重矩阵的…

革新网络管理:拉线网套技术引领行业新趋势

根据QYResearch调研团队的最新力作《全球拉线网套市场报告2023-2029》预测&#xff0c;到2029年&#xff0c;全球拉线网套市场的规模有望达到11.7亿美元&#xff0c;且在未来几年内&#xff0c;将以3.5%的复合年增长率&#xff08;CAGR&#xff09;持续扩张。 在全球范围内&…

HTB:Devel[WriteUP]

目录 连接至HTB服务器并启动靶机 1.What is the name of the service is running on TCP port 21 on the target machine? 使用nmap对靶机TCP端口进行开放扫描 2.Which basic FTP command can be used to upload a single file onto the server? 尝试匿名连接至靶机FTP服…

Hadoop集群的高可用(HA)-(2、搭建resourcemanager的高可用)

第一步&#xff1a;检查mapred-site.xml &#xff0c;里面只有yarn配置和historyServer的配置&#xff0c;不需要修改 第二步&#xff1a;修改yarn-site.xml <?xml version"1.0"?> <!-- Licensed under the Apache License, Version 2.0 (the "Lic…

golang笔记

golang笔记 一、内存逃逸 本应在栈中内存,被分配到了堆中 1 返回指针对象 在外部被使用 2 reutrn 函数 使用了上面方法的敞亮 3 入参是interface{} 动态参数 4 make超过栈大小 -gcflags"-m"查看分配内存信息 返回变量vs返回指针 返回变量, 会多一步复制变量, 返回…

纹理分析——统计分析方法

一. 灰度共生矩阵法(Gray Level Co-occurrence Matrix, GLCM ) 灰度共生矩阵又称为灰度空间相关矩阵&#xff0c;是通过研究灰度的空间相关特性来描述纹理的常用方法。&#xff08;也称为联合概率矩阵&#xff09;它作为传统的图像纹理分析方法已广泛应用于数字图像处理的许多…

IT维修记录表导入接口的思路

上篇文章讲了IT设备信息表的导入接口的思路&#xff0c;这篇文章趁热打铁&#xff0c;把IT维修记录表的导入接口的思路给说一下。 首先我们要知道IT维修记录表的数据是什么来的&#xff1f;这个问题必须要搞懂&#xff0c;不搞懂的话对接下来的思路其实是不利的。IT维修记录表…

场景解决方案丨迎战电商大促,企业管理跟踪驾驶舱助力中小企业打赢决胜之战

该方案已沉淀为➡️订单物流信息跟踪模板&#xff0c;点击&#x1f517;即可体验 随着互联网技术的发展和市场经济的变化&#xff0c;各行业的线上竞争愈发激烈。一方面&#xff0c;互联网平台凭借便捷的服务和丰富的产品吸引了大量客户&#xff1b;另一方面&#xff0c;复杂多…