当前位置: 首页 > news >正文

qt 多进程使用共享内存 ,加速数据读写,进程间通信 共享内存

Summary:

项目中我们有时需要使用共享内存共享数据,这样,数据不用进程IO读写,加进数据加载和落地;

程序退出时,再保存到本地;速度提升数十倍;

Part1:QSharedMemory

Windows平台下进程间通信常用方式有管道、文件映射、Socket通信和共享内存等,这里详细介绍一下Qt的共享内存机制。

Qt 框架提供了多种 IPC 技术,其中 QSharedMemory 是一种高效的共享内存方式,可以实现多个进程之间快速交换数据。本文将详细讲解 QSharedMemory 的概念、用法及其主要函数的用途;

Header:

#include <QSharedMemory>

qmake:

QT += core

Since:

Qt 4.4

Inherits:

QObject

  • List of all members, including inherited members
  • Obsolete members

1.QSharedMemory 的核心特点

    唯一键(Key)标识:
        每块共享内存通过唯一的键(字符串)标识。
        不同进程通过相同的键连接到共享内存。

    线程安全性:
        提供锁机制(lock() 和 unlock())以保护共享内存的读写。

    跨平台支持:
        Qt 的跨平台特性使 QSharedMemory 可以在不同操作系统上无缝使用。

2. QSharedMemory 的工作流程

共享内存的基本使用可以分为以下几个步骤:

    创建共享内存:
        第一个进程通过 create(size) 创建一块共享内存。
        分配的大小由数据的存储需求决定。

    附加到共享内存:
        其他进程通过 attach() 方法连接到已有的共享内存。

    数据读写:
        通过 lock() 和 unlock() 保证线程安全,获取内存指针后读写数据。

    释放共享内存:
        调用 detach() 断开与共享内存的连接。

3.QSharedMemory 常用函数

1. 构造函数与析构函数
QSharedMemory(const QString &key, QObject *parent = nullptr)创建一个 QSharedMemory 对象,并指定共享内存的键(key)。key 是共享内存的唯一标识符,多个进程通过相同的 key 访问同一块共享内存。~QSharedMemory()析构函数,释放共享内存资源。2. 共享内存的创建与销毁
bool create(int size, QSharedMemory::AccessMode mode = ReadWrite)创建大小为 size 的共享内存段。mode 指定共享内存的访问模式:QSharedMemory::ReadOnly:只读模式。QSharedMemory::ReadWrite:读写模式(默认)。如果共享内存已存在,则返回 false。bool attach(QSharedMemory::AccessMode mode = ReadWrite)附加到已存在的共享内存段。mode 指定访问模式(同上)。如果附加成功,返回 true。bool detach()从共享内存段分离。分离后,进程不再访问共享内存,但共享内存段仍然存在。void setKey(const QString &key)设置共享内存的键(key)。QString key() const返回共享内存的键。void setNativeKey(const QString &key)设置平台原生的共享内存键(适用于需要直接使用系统共享内存键的场景)。QString nativeKey() const返回平台原生的共享内存键。3. 共享内存的访问
void *data()返回指向共享内存数据的指针。如果共享内存未附加或未创建,返回 nullptr。const void *constData() const返回指向共享内存数据的常量指针。适用于只读访问。int size() const返回共享内存段的大小(以字节为单位)。4. 共享内存的锁定与解锁
bool lock()锁定共享内存,确保当前进程独占访问。如果锁定成功,返回 true。bool unlock()解锁共享内存,允许其他进程访问。如果解锁成功,返回 true。5. 错误处理
QSharedMemory::SharedMemoryError error() const返回最后一次发生的错误类型。错误类型包括:QSharedMemory::NoError:无错误。QSharedMemory::PermissionDenied:权限不足。QSharedMemory::InvalidSize:无效的大小。QSharedMemory::KeyError:键错误。QSharedMemory::AlreadyExists:共享内存已存在。QSharedMemory::NotFound:共享内存未找到。QSharedMemory::LockError:锁定失败。QSharedMemory::OutOfResources:系统资源不足。QSharedMemory::UnknownError:未知错误。QString errorString() const返回最后一次错误的描述信息。6. 共享内存的状态
bool isAttached() const检查当前进程是否已附加到共享内存段。如果已附加,返回 true。

Part3: 读写文件样例:

写样例:

QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
QDataStream out(&buffer);
out.setByteOrder(QDataStream::LittleEndian);// 假设 metaInfo 是已填充的结构体
out.writeRawData((char*)&metaInfo, sizeof(FileMetaInfo));// 将 buffer 数据写入共享内存
sharedMemory.lock();
memcpy(sharedMemory.data(), buffer.data().constData(), buffer.size());
sharedMemory.unlock();

读样例:

    QBuffer buffer;qDebug() << "sharedMemory.size():" << sharedMemory.size();buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());buffer.open(QIODevice::ReadOnly);buffer.seek(0);qDebug() << "Buffer size:" << buffer.size();qDebug() << "First bytes:" << QByteArray::fromRawData((char*)sharedMemory.constData(), 16).toHex();QDataStream inStream(&buffer);inStream.device()->seek(0);  // 确保 QDataStream 位置正确inStream.setByteOrder(QDataStream::LittleEndian);FileMetaInfo metaPtr ;inStream.readRawData((char*)&metaPtr, sizeof(FileMetaInfo));qDebug() << "File:" << metaPtr.fileName<< "Size:" << metaPtr.fileSize<< "Offset:" << metaPtr.dataOffset;
读写多个文件样例:
共享内存结构定义
#include <QSharedMemory>
#include <QBuffer>
#include <QDataStream>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QVector>// 定义文件元信息结构
#pragma pack(1)
struct FileMetaInfo {char fileName[256];    // 文件名qint64 fileSize;     // 文件大小qint64 dataOffset;   // 文件数据在共享内存中的偏移量FileMetaInfo() : fileSize(0), dataOffset(0) {memset(fileName, 0, sizeof(fileName)); // 初始化 fileName 为空字符串}
};
#pragma pack()
// 定义共享内存的索引区大小(假设最多存储 10 个文件)
const int MAX_FILES = 10;
const int INDEX_SIZE = MAX_FILES * sizeof(FileMetaInfo);
进程A:写入文件到共享内存
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建共享内存对象QSharedMemory sharedMemory("MySharedMemory");// 假设要写入的文件列表QStringList filePaths = { "file1.txt", "file2.txt", "file3.txt" };// 计算共享内存总大小(索引区 + 数据区)qint64 totalDataSize = 0;for (const QString &filePath : filePaths) {QFile file(filePath);if (file.open(QIODevice::ReadOnly)) {totalDataSize += file.size();file.close();}}qint64 totalSharedMemorySize = INDEX_SIZE + totalDataSize;// 创建共享内存if (!sharedMemory.create(totalSharedMemorySize)) {qDebug() << "Failed to create shared memory:" << sharedMemory.errorString();return 1;}// 写入索引区和数据区sharedMemory.lock();// 写入索引区QBuffer indexBuffer;indexBuffer.open(QBuffer::ReadWrite);QDataStream indexStream(&indexBuffer);qint64 currentDataOffset = INDEX_SIZE; // 数据区从索引区之后开始for (const QString &filePath : filePaths) {QFile file(filePath);if (file.open(QIODevice::ReadOnly)) {FileMetaInfo metaInfo;metaInfo.fileName = QFileInfo(file).fileName();metaInfo.fileSize = file.size();metaInfo.dataOffset = currentDataOffset;// 写入索引信息indexStream << metaInfo.fileName << metaInfo.fileSize << metaInfo.dataOffset;// 写入文件数据到共享内存char *to = (char*)sharedMemory.data() + currentDataOffset;file.read(to, metaInfo.fileSize);currentDataOffset += metaInfo.fileSize;file.close();}}// 将索引区数据写入共享内存char *indexTo = (char*)sharedMemory.data();const char *indexFrom = indexBuffer.data().data();memcpy(indexTo, indexFrom, indexBuffer.size());sharedMemory.unlock();qDebug() << "Files written to shared memory.";return a.exec();
}
进程B:从共享内存读取文件
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建共享内存对象QSharedMemory sharedMemory("MySharedMemory");// 附加到共享内存if (!sharedMemory.attach()) {qDebug() << "Failed to attach to shared memory:" << sharedMemory.errorString();return 1;}// 读取索引区sharedMemory.lock();QBuffer indexBuffer;indexBuffer.setData((char*)sharedMemory.constData(), INDEX_SIZE);indexBuffer.open(QBuffer::ReadOnly);QDataStream indexStream(&indexBuffer);QVector<FileMetaInfo> fileMetaInfos;while (!indexStream.atEnd()) {FileMetaInfo metaInfo;indexStream >> metaInfo.fileName >> metaInfo.fileSize >> metaInfo.dataOffset;fileMetaInfos.append(metaInfo);}// 读取文件数据for (const FileMetaInfo &metaInfo : fileMetaInfos) {QByteArray fileData(metaInfo.fileSize, 0);const char *from = (char*)sharedMemory.constData() + metaInfo.dataOffset;memcpy(fileData.data(), from, metaInfo.fileSize);// 将文件数据保存到本地QFile file(metaInfo.fileName);if (file.open(QIODevice::WriteOnly)) {file.write(fileData);file.close();qDebug() << "File saved:" << metaInfo.fileName;}}sharedMemory.unlock();// 分离共享内存sharedMemory.detach();return a.exec();
}

代码说明

  1. 共享内存结构

    • 共享内存分为索引区和数据区。

    • 索引区存储文件的元信息(文件名、大小、偏移量)。

    • 数据区存储实际的文件数据。

  2. 进程A

    • 计算共享内存的总大小(索引区 + 数据区)。

    • 将文件的元信息写入索引区。

    • 将文件数据写入数据区。

  3. 进程B

    • 从索引区读取文件的元信息。

    • 根据元信息从数据区读取文件数据,并保存到本地。

  4. 共享内存的锁定与解锁

    • 在读写共享内存时,使用lock()unlock()确保数据一致性。

  5. 文件管理

    • 支持多个文件的读写,通过索引区管理文件的元信息。


运行步骤

  1. 编译并运行进程A,将文件写入共享内存。

  2. 编译并运行进程B,从共享内存读取文件并保存到本地。

Part4: 注意事项:

  • 需要确保文件名和文件路径的唯一性,避免冲突。

  • 在实际应用中,可能需要处理更多的错误情况(如文件不存在、共享内存不足等)。

  • 共享内存的键:多个进程必须使用相同的键才能访问同一块共享内存。

  • 锁定与解锁:在读写共享内存时,必须使用 lock()unlock() 确保数据一致性。

  • 错误处理:始终检查 create()attach() 的返回值,并处理可能的错误。

  • 共享内存的大小:确保共享内存的大小足够容纳要存储的数据。

  • 通过这种方式,可以在共享内存中高效地管理多个文件,并通过索引文件实现快速访问

可能遇到的问题:

1.读写,请使用相关的方式:

 indexStream.setByteOrder(QDataStream::LittleEndian);

2.

相关文章:

qt 多进程使用共享内存 ,加速数据读写,进程间通信 共享内存

Summary: 项目中我们有时需要使用共享内存共享数据&#xff0c;这样&#xff0c;数据不用进程IO读写&#xff0c;加进数据加载和落地&#xff1b; 程序退出时&#xff0c;再保存到本地&#xff1b;速度提升数十倍&#xff1b; Part1:QSharedMemory Windows平台下进程间通信…...

OpenHarmony-分布式硬件关键技术

前言&#xff1a; OpenHarmony是一款面向未来万物互联场景的操作系统&#xff0c;其设计采用了分布式架构。那么OpenHarmony相比于传统操作系统有哪些关键的分布式技术&#xff0c;本文主要介绍分布式硬件设计理念、跨端分布式硬件核心挑战、以及OpenHarmony分布式硬件平台关键…...

idea超级AI插件,让 AI 为 Java 工程师

引言​ 用户可在界面中直接通过输入自然语言的形式描述接口的需求&#xff0c;系统通过输入的需求自动分析关键的功能点有哪些&#xff0c;并对不确定方案的需求提供多种选择&#xff0c;以及对需求上下文进行补充&#xff0c;用户修改确定需求后&#xff0c;系统会根据需求设…...

深入Flink运行时架构:JobManager与TaskManager协作全解析

深入Flink运行时架构:JobManager与TaskManager协作全解析 一、Flink分布式执行模型剖析 1.1 运行时架构全景视图 核心组件交互关系: #mermaid-svg-tMSqMSsKP6vwUZi3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-s…...

OSPF-单区域的配置

一、单区域概念&#xff1a; 单区域OSPF中&#xff0c;整个网络被视为一个区域&#xff0c;区域ID通常为0&#xff08;骨干区域&#xff09;。所有的路由器都在这个区域内交换链路状态信息。 补充知识点&#xff1a; OSPF为何需要loopback接口&#xff1a; 1.Loopback接口的…...

每日OJ_牛客_过桥_贪心+BFS_C++_Java

目录 牛客_过桥_贪心BFS 题目解析 C代码 Java代码 牛客_过桥_贪心BFS 过桥 描述&#xff1a; dd被困在了一个迷幻森林&#xff0c;现在她面前有一条凶险的大河&#xff0c;河中央有n个神奇的浮块&#xff0c;浮块按1∼n1顺序标号&#xff0c;但两两并不相接&…...

K8S学习之基础二十七:k8s中daemonset控制器

k8s中DaemonSet控制器 ​ DaemonSet控制器确保k8s集群中&#xff0c;所有节点都运行一个相同的pod&#xff0c;当node节点增加时&#xff0c;新节点也会自动创建一个pod&#xff0c;当node节点从集群移除&#xff0c;对应的pod也会自动删除。删除DaemonSet也会删除创建的pod。…...

79.ScottPlot的MVVM实现 C#例子 WPF例子

如何通过数据绑定在 WPF 中实现动态图像显示 在 WPF 应用程序中&#xff0c;通过数据绑定实现动态图像显示是一种高效且优雅的方式。以下是一个简单的教程&#xff0c;展示如何使用 ScottPlot.WPF 库和 MVVM 模式来实现这一功能。 第一步&#xff1a;安装必要的 NuGet 包 首…...

第44天:WEB攻防-PHP应用SQL盲注布尔回显延时判断报错处理增删改查方式

时间轴&#xff1a; 44天知识点总结&#xff1a; 1.mysql的增删改查功能 2.根据源码sql语句的三种sql注入&#xff1a;布尔盲注&#xff08;必须要有回显&#xff09; 延时判断&#xff08;都可以&#xff09; 报错回显&#xff08;必须要有报错处理机制&#xff09; 3.两个cms…...

说说人工智能

1. 人工智能与机器学习 核心进展 人工智能&#xff08;AI&#xff09;与机器学习&#xff08;ML&#xff09;已从理论研究全面渗透到实际应用中。深度学习模型如Transformer架构在自然语言处理&#xff08;NLP&#xff09;和计算机视觉&#xff08;CV&#xff09;领域实现突破…...

懒加载(Lazy Loading):原理、实现与优化策略

懒加载&#xff08;Lazy Loading&#xff09; 是一种优化网页性能的技术&#xff0c;主要用于延迟加载非关键资源&#xff08;如图片、视频、脚本等&#xff09;&#xff0c;直到它们真正需要被使用时才加载。懒加载可以显著减少页面初始加载时间&#xff0c;降低带宽消耗&…...

HTML5(Web前端开发笔记第一期)

p.s.这是萌新自己自学总结的笔记&#xff0c;如果想学习得更透彻的话还是请去看大佬的讲解 目录 三件套标签标题标签段落标签文本格式化标签图像标签超链接标签锚点链接默认链接地址 音频标签视频标签 HTML基本骨架综合案例->个人简介列表表格表单input标签单选框radio上传…...

Linux学习(十五)(故障排除(ICMP,Ping,Traceroute,网络统计,数据包分析))

故障排除是任何 Linux 用户或管理员的基本技能。这涉及识别和解决 Linux 系统中的问题。这些问题的范围包括常见的系统错误、硬件或软件问题、网络连接问题以及系统资源的管理。Linux 中的故障排除过程通常涉及使用命令行工具、检查系统和应用程序日志文件、了解系统进程&#…...

SVN 拉取,文件冲突 解决办法

情景 svn 在拉取代码时 提示 已跳过&#xff0c;其余有冲突 &#xff0c;警告至少还有一个的文件处于冲突状态 导致文件拉取失败 一、原因 版本库和本地工作副本之间存在文件冲突&#xff0c;导致文件无法正常拉取。 二、 Terminal 窗口解决办法 1.查看冲突文件 在 Termin…...

【实战ES】实战 Elasticsearch:快速上手与深度实践-8.1.1基于ES的语义搜索(BERT嵌入向量)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 基于Elasticsearch与BERT的语义搜索架构设计与实战1. 传统搜索的局限性与语义搜索的崛起1.1 关键词搜索 vs 语义搜索1.2 Elasticsearch向量检索演进历程关键版本特性对比 2.…...

【Node.js】--- win11安装 Node.js

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【Node.js】--- win11安装 Node.js 开发环…...

【技海登峰】Kafka漫谈系列(九)SpringBoot整合Kafka多数据源配置

【技海登峰】Kafka漫谈系列(九)SpringBoot整合Kafka多数据源配置 Kafka官方提供了基于Java实现的客户端kafka-clients,用于提供生产者和消费者的基本能力。在此基础上,Spring for Apache Kafka(spring-kafka)项目对该原生客户端进行了基于Spring特性的抽象与封装,实现了基…...

【MySQL篇】基本查询实战OJ

本篇是基于上篇mysql基本查询的一些OJ题 MySQL基本查询传送门&#xff1a;【MySQL篇】MySQL基本查询详解-CSDN博客 批量插入数据_牛客题霸_牛客网 insert语句 insert into actor values (1,PENELOPE,GUINESS,2006-02-15 12:34:33); insert into actor values (2,NICK,WAHLBER…...

侯捷 C++ 课程学习笔记:C++内存管理机制

内存管理从平地到万丈高楼 内存管理入门&#xff08;Memory Management 101&#xff09; 需要具有动态分配并使用memory&#xff08;存储&#xff08;器&#xff09;&#xff0c;&#xff08;计算机的&#xff09;内存&#xff09;&#xff0c;使用过C标准库的容器&#xff0…...

java后端开发day31--集合进阶(一)-----Collection集合List集合数据结构1

&#xff08;以下内容全部来自上述课程&#xff09; 1.集合体系结构 List系列集合&#xff1a;添加的元素是有序、可重复、有索引。 Set系列集合&#xff1a;添加的元素是无序、不重复、无索引。 2.Collection集合 Collection是单列集合的祖宗接口&#xff08;不可直接创建…...

TA学习之路——1.4 MVP矩阵运算

1.变换矩阵的意义 1.将3D物体转化到2D平面 2.为各个空间的运用做准备 2.MVP矩阵代表什么 MVP矩阵分别是模型&#xff08;Model&#xff09;、观察&#xff08;View&#xff09;、投影&#xff08;Projecttion)三个矩阵。我们顶点坐标起始于局部空间&#xff08;Local Space)…...

Java数据结构第二十期:解构排序算法的艺术与科学(二)

专栏&#xff1a;Java数据结构秘籍 个人主页&#xff1a;手握风云 目录 一、常见排序算法的实现 1.1. 直接选择排序 1.2. 堆排序 1.3. 冒泡排序 1.4. 快速排序 一、常见排序算法的实现 1.1. 直接选择排序 每⼀次从待排序的数据元素中选出最小的⼀个元素&#xff0c;存放在…...

【机器学习】主成分分析法(PCA)

【机器学习】主成分分析法&#xff08;PCA&#xff09; 一、摘要二、主成分分析的基本概念三、主成分分析的数学模型五、主成分分析法目标函数公式推导&#xff08;梯度上升法求解目标函数&#xff09;六、梯度上升法求解目标函数第一个主成分七、求解前n个主成分及PCA在数据预…...

perl、python、tcl语法中读写Excel的模块

perl、python、tcl语法中读写Excel的模块 perl、python、tcl语法中存在读写xls和xlsx格式的模块分别有&#xff1a; python ‌读取 Excel‌ ‌xlrd‌&#xff1a;支持传统 .xls 格式的读取‌ pandas‌&#xff1a;通过 read_excel() 方法支持 .xls 和 .xlsx 格式‌ ‌写入 …...

libwebsockets实现异步websocket客户端,服务端异常断开可重连

libwebsockets websocket客户端基本流程网上都有&#xff0c;我只额外优化了重连机制。 在服务器异常断开时不触发LWS_CALLBACK_CLOSED或LWS_CALLBACK_CLIENT_CONNECTION_ERROR&#xff0c;导致无法自动重连 通过定时检查链接是否可写入判断链接是否有效 // 判断wsi是否可用if …...

CAD球体密堆积3D插件V2.0

插件介绍 CAD球体密堆积3D插件V2.0版本可在AutoCAD内建立球体堆积模型&#xff0c;插件采取模拟球体在重力作用下的堆积行为&#xff0c;可生成超密堆积的几何模型及进行堆积过程的动态展示。 插件优化重力堆积物理引擎&#xff0c;新增堆积可视化界面&#xff0c;可直观查看…...

【Linux】线程池、单例模式、死锁

线程池 一.线程池1.日志和策略模式2.线程池1.Task.hpp2.Thread.hpp3.ThreadPool.hpp4.ThreadPool.cc 二.线程安全与重入问题三.线程安全的单例模式1.饿汉模式2.懒汉模式3.懒汉模式线程池1.ThreadPool.hpp2.ThreadPool.cc 四.死锁的概念1.死锁2.死锁的四个必要条件3.避免死锁 五…...

AI+视频监控电力巡检:EasyCVR视频中台方案如何赋能电力行业智能化转型

随着电力行业的快速发展&#xff0c;电力设施的安全性、稳定性和运维效率变得至关重要。传统视频监控系统在实时性、智能化及多系统协同等方面面临严峻挑战。EasyCVR视频中台解决方案作为一种先进的技术手段&#xff0c;在电力行业中得到了广泛应用&#xff0c;为电力设施的监控…...

centos8.0系统部署zabbix6.0监控

centos8.0系统部署zabbix6.0监控 一、部署过程1、确认系统版本2、主机基础环境设置3、安装MySQL 8.0数据库3.1 安装MySQL 8.0仓库3.2 安装软件3.3 设置root用户密码3.4 创建zabbix数据库&#xff0c;授权用户 4、配置zabbix6.0仓库5、安装zabbix服务端软件6、导入zabbix数据表7…...

江科大51单片机笔记【12】AT24C02(I2C总线)

写在前言 此为博主自学江科大51单片机&#xff08;B站&#xff09;的笔记&#xff0c;方便后续重温知识 在后面的章节中&#xff0c;为了防止篇幅过长和易于查找&#xff0c;我把一个小节分成两部分来发&#xff0c;上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识…...

电脑一直重启怎么解决 原因及解决方法

电脑一直重启的故障状态&#xff0c;不仅影响电脑的正常使用&#xff0c;还可能导致数据丢失或损坏。那么&#xff0c;电脑一直重启是什么原因呢&#xff1f;又该如何解决呢&#xff1f;下面将为大家介绍电脑一直重启的常见原因和解决方法&#xff0c;帮助您恢复电脑的正常工作…...

内网安全防护新思路 —— HFish + ELK 与 T-Pot 全面蜜罐系统比较分析

在当前网络安全环境日益复杂的背景下&#xff0c;企业和组织面临着来自外部与内部的多种威胁。为了更好地了解攻击者行为、捕获恶意活动并及时响应&#xff0c;部署蜜罐&#xff08;Honeypot&#xff09;系统已成为提升内网安全防护的重要手段。本文将重点介绍两种内网蜜罐防护…...

「 机器人 」扑翼飞行器通过总气动力控制四自由度运动方法

一、前言 在扑翼飞行中,总气动力(Total Aerodynamic Force)是指扑翼在运动过程中受到的所有空气动力作用的合力。它是由以下两种主要力的合成结果: 1. 升力(Lift, ):垂直于空气流方向的力,用于支持飞行器(或生物)的重量。 2. 阻力(Drag, ):平行于空气流方向的力,…...

写了一个二叉树构造函数和画图函数,方便debug

代码 class TreeNode(object):def __init__(self, val, leftNone, rightNone):self.val valself.left leftself.right rightdef construct_tree(nodes):if not nodes:return Noneroot TreeNode(nodes[0])queue [root]index 1while index < len(nodes):node queue.p…...

【prompt实战】知乎问题解答专家

本文原创作者&#xff1a;姚瑞南 AI-agent 大模型运营专家&#xff0c;先后任职于美团、猎聘等中大厂AI训练专家和智能运营专家岗&#xff1b;多年人工智能行业智能产品运营及大模型落地经验&#xff0c;拥有AI外呼方向国家专利与PMP项目管理证书。&#xff08;转载需经授权&am…...

元组(Tuple)详解——c#

在C#中&#xff0c;元组&#xff08;Tuple&#xff09; 是一种轻量级的数据结构&#xff0c;用于将多个值组合成一个单一的对象。元组非常适合在不需要定义新类或结构体的情况下&#xff0c;临时存储和传递多个相关的值。 C# 中的元组有两种形式&#xff1a; 传统元组&#xf…...

Maven工具基础知识(一)

第一章、Maven概述 一、概述 官网地址&#xff1a;Welcome to Apache Maven – Maven Maven是一个基于Java的项目管理工具&#xff0c;专注于项目构建、依赖管理和项目信息标准化。其核心目标 是简化开发流程&#xff0c;通过标准化项目结构和自动化构建流程&#xff…...

AI模型的构建过程是怎样的(下)

你好,我是舒旻。 上节课,我们讲了一个模型构建的前 2 个环节,模型设计和特征工程。今天,我们继续来讲模型构建的其他 3 个环节,说说模型训练、模型验证和模型融合中,算法工程师的具体工作内容,以及 AI 产品经理需要掌握的重点。 模型训练 模型训练是通过不断训练、验证…...

力扣hot100_二叉树

二叉树的建立与遍历 #include <iostream> #include <vector> #include <queue> using namespace std;// 定义二叉树节点 struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} };// 函数&…...

如何制作Windows系统盘、启动盘?(MediaCreationTool_22H2)

文章目录 每日一句正能量前言一、准备工作二、制作启动盘后记 每日一句正能量 每个在你生命里出现的人&#xff0c;都有原因。喜欢你的人给你温暖关心。你喜欢的人让你学会爱和付出&#xff0c;不喜欢你的人让你自省成长。你不喜欢的人教会你宽容尊重&#xff0c;没有人是偶然出…...

分布式光伏发电的发展现状与前景

分布式光伏发电的发展现状与前景 1、分布式光伏发电的背景2、分布式光伏发电的分类2.1、集中式光伏发电2.1.1、特点、原则2.1.2、优点2.1.3、缺点 2.2、分布式光伏发电2.2.1、特点、原则2.2.2、优点2.2.3、缺点 2.3、对比 3、分布式光伏发电的现状4、分布式光伏发电的应用场景4…...

【AI大模型智能应用】Deepseek生成测试用例

在软件开发过程中&#xff0c;测试用例的设计和编写是确保软件质量的关键。 然而&#xff0c;软件系统的复杂性不断增加&#xff0c;手动编写测试用例的工作量变得异常庞大&#xff0c;且容易出错。 DeepSeek基于人工智能和机器学习&#xff0c;它能够依据软件的需求和设计文…...

NVIDIA k8s-device-plugin源码分析与安装部署

在《kubernetes Device Plugin原理与源码分析》一文中&#xff0c;我们从源码层面了解了kubelet侧关于device plugin逻辑的实现逻辑&#xff0c;本文以nvidia管理GPU的开源github项目k8s-device-plugin为例&#xff0c;来看看设备插件侧的实现示例。 一、Kubernetes Device Pl…...

面向联邦学习隐私保护的同态加密库优化算法研究

面向联邦学习隐私保护的同态加密库优化算法研究 一、引言 联邦学习作为一种新兴的分布式机器学习范式,允许各参与方在不共享原始数据的前提下协同训练模型,有效解决了数据孤岛和隐私保护问题。同态加密作为实现联邦学习隐私保护的关键技术之一,能够在密文上直接进行特定运算…...

20250212:linux系统DNS解析卡顿5秒的bug

问题: 1:人脸离线识别记录可以正常上传云端 2:人脸在线识别请求却一直超时 3:客户使用在线网络 思路:...

动态规划 -第1篇

前言&#xff1a;在计算机科学中&#xff0c;动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是解决最优化问题的一种重要方法。通过将大问题拆解为小问题&#xff0c;动态规划不仅能够显著降低计算复杂度&#xff0c;还能提高效率。无论是经典的背包问…...

uni-app打包成H5使用相对路径

网上找了一圈&#xff0c;没用&#xff0c;各种试&#xff0c;终于给试出来了&#xff0c;导致打包之后请求的路径没有带上域名 直接去 config.js文件里面的baseUrl路径改成空字符就行了&#xff0c;千万别写/...

【每日学点HarmonyOS Next知识】swiper样式、日期选择、自定义弹窗键盘、文本组件换行、富文本适配

1、HarmonyOS swiper组件样式&#xff1f; 可在样式中设置即可&#xff0c;参考如下demo Entry Component struct SwiperDemo {private swiperController: SwiperController new SwiperController();build() {Column({ space: 5 }) {Swiper(this.swiperController) {Text(0)…...

STM32 I2C驱动开发全解析:从理论到实战 | 零基础入门STM32第五十步

主题内容教学目的/扩展视频I2C总线电路原理&#xff0c;跳线设置&#xff0c;I2C协议分析。驱动程序与调用。熟悉I2C总线协议&#xff0c;熟练调用。 师从洋桃电子&#xff0c;杜洋老师 &#x1f4d1;文章目录 引言一、I2C驱动分层架构二、I2C总线驱动代码精析2.1 初始化配置&a…...

Ragflow技术栈分析及二次开发指南

Ragflow是目前团队化部署大模型+RAG的优质方案,不过其仍不适合直接部署使用,本文将从实际使用的角度,对其进行二次开发。 1. Ragflow 存在问题 Ragflow 开源仓库地址:https://github.com/infiniflow/ragflow Ragflow 当前版本: v0.17.0 Ragflow 目前主要存在以下问题: …...