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

鸿蒙进阶——驱动框架UHDF 机制核心源码解读(一)

文章大纲

  • 引言
  • 一、uhdf 概述
  • 二、uhdf 的核心参与角色
    • 1、drivers/hdf_core/adapter/uhdf2/manager/device_manager.c
      • 1.1、drivers/hdf_core/framework/core/manager/src/devmgr_service.c#DevmgrServiceGetInstance通过objectId获取IDevmgrService实例
      • 1.2、drivers/hdf_core/framework/core/shared/src/hdf_object_manager.c#HdfObjectManagerGetObject——>HdfObjectManagerGetCreators
    • 2、drivers/hdf_core/adapter/uhdf2/host/devhost.c、driver_loader_full.c和device_info.hcs
  • 三、hdf_device_manager的启动
    • 1、DevmgrServiceGetInstance()
    • 2、IDevmgrService#StartService(instance)——>drivers/hdf_core/framework/core/manager/src/devmgr_service.c#DevmgrServiceStartService
      • 2.1、DevSvcManagerStartService()
      • 2.2、DevmgrServiceStartDeviceHosts

引言

前面两篇文章从理论的角度简单介绍了下HDF驱动框架的基本理论知识和原理,接下来就从源码角度介绍下UHDF核心工作流程。

一、uhdf 概述

区别于传统的硬件驱动khdf,OpenHarmony还设计了一层uhdf,本质上就是一个应用进程,主要是面向用户层提供与驱动的交互接口层。与khdf一样每一个uhdf 都需要注册到device_info.hcs文件内,当然了uhdf 正常工作时是离不开khdf的。

二、uhdf 的核心参与角色

NNRT HOST 的启动也是由uhdf 驱动的,以下是uhdf工作流程

1、drivers/hdf_core/adapter/uhdf2/manager/device_manager.c

device_manager.c承担着所有硬件外设的管理角色,所有设备的host_service服务都由它统一管理,再由devhost.c创建对应的xxx_host_service需要主动注册到device_manager中,当需要使用时直接通过device_manager获取并使用。

int main()
{HDF_LOGI("start hdf device manager");int status = HDF_FAILURE;struct IDevmgrService* instance = DevmgrServiceGetInstance();if (instance->StartService != NULL) {status = instance->StartService(instance);}(void)DevMgrUeventReceiveStart();DevMgrRegisterDumpFunc();if (status == HDF_SUCCESS) {struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)instance;struct HdfMessageLooper *looper = &fullService->looper;if ((looper != NULL) && (looper->Start != NULL)) {looper->Start(looper);}}HDF_LOGE("starting device manager service failed, status is %{public}d", status);return status;
}

1.1、drivers/hdf_core/framework/core/manager/src/devmgr_service.c#DevmgrServiceGetInstance通过objectId获取IDevmgrService实例

struct IDevmgrService *DevmgrServiceGetInstance(void)
{static struct IDevmgrService *instance = NULL;if (instance == NULL) {instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);}return instance;
}

1.2、drivers/hdf_core/framework/core/shared/src/hdf_object_manager.c#HdfObjectManagerGetObject——>HdfObjectManagerGetCreators

不同的Service 有各自对应的HdfObjectManagerGetCreators 实现。

2、drivers/hdf_core/adapter/uhdf2/host/devhost.c、driver_loader_full.c和device_info.hcs

.hcs是开发者注册hdf驱动列表的配置文件,再编译后会结合SeLinux 策略重新编译整理成.hcg文件,同时devhost.c 成为一个可执行文件,当需要拉起对应的uhdf _host_service时被执行,所以有可能被执行多次,而需要注意的是dev_host相当于是只是一个空壳,还需要driver_loader_full.c 来把真正这个uhdf 驱动的真正的业务逻辑对应的so 加载进来,才能成为一个真正的uhdf 设备驱动并且将其句柄缓存至系统的设备驱动列表中。以nnrt_host为例,当我们把nnrt_host 的uhdf驱动的信息添加到.hcs驱动列表文件后,当系统遍历时就会去执行devhost.c的main函数解析.hcg的信息,创建对应的nnrt_host的实例句柄并且加载其相应的so,再把符号连接到对应的位置,拉起对应的进程。

NNRT HOST 启动三部曲在这里插入图片描述

三、hdf_device_manager的启动

系统启动过程中首先是由脚本触发device_manager#main函数执行

int main()
{HDF_LOGI("start hdf device manager");int status = HDF_FAILURE;struct IDevmgrService* instance = DevmgrServiceGetInstance();...if (instance->StartService != NULL) {status = instance->StartService(instance);}(void)DevMgrUeventReceiveStart();DevMgrRegisterDumpFunc();if (status == HDF_SUCCESS) {struct DevmgrServiceFull *fullService = (struct DevmgrServiceFull *)instance;struct HdfMessageLooper *looper = &fullService->looper;if ((looper != NULL) && (looper->Start != NULL)) {looper->Start(looper);}}...return status;
}

1、DevmgrServiceGetInstance()

通过传入HDF_OBJECT_ID_DEVMGR_SERVICE作为objectId 获取IDevmgrService 的指针。

drivers/hdf_core/framework/core/manager/src/devmgr_service.c
struct IDevmgrService *DevmgrServiceGetInstance(void)
{static struct IDevmgrService *instance = NULL;if (instance == NULL) {instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);}return instance;
}

然后drivers/hdf_core/framework/core/shared/src/hdf_object_manager.c#HdfObjectManagerGetObject 里触发Create函数指针

struct HdfObject *HdfObjectManagerGetObject(int objectId)
{struct HdfObject *object = NULL;const struct HdfObjectCreator *targetCreator = HdfObjectManagerGetCreators(objectId);if ((targetCreator != NULL) && (targetCreator->Create != NULL)) {// 触发函数指针Create 执行object = targetCreator->Create();if (object != NULL) {object->objectId = objectId;}}return object;
}

在drivers/hdf_core/framework/core/common/src/devlite_object_config.c里定义了一个常量结构体,可以根据objectId拿到对应的成员变量并执行其Create指针指向的函数

const struct HdfObjectCreator *HdfObjectManagerGetCreators(int objectId)
{int numConfigs = sizeof(g_liteObjectCreators) / sizeof(g_liteObjectCreators[0]);if ((objectId >= 0) && (objectId < numConfigs)) {return &g_liteObjectCreators[objectId];}return NULL;
}static const struct HdfObjectCreator g_liteObjectCreators[] = {[HDF_OBJECT_ID_DEVMGR_SERVICE] ={.Create = DevmgrServiceCreate,.Release = DevmgrServiceRelease,},[HDF_OBJECT_ID_DEVSVC_MANAGER] ={.Create = DevSvcManagerExtCreate,.Release = DevSvcManagerExtRelease,},[HDF_OBJECT_ID_DEVHOST_SERVICE] ={.Create = DevHostServiceCreate,.Release = DevHostServiceRelease,},[HDF_OBJECT_ID_DRIVER_INSTALLER] ={.Create = DriverInstallerCreate,.Release = NULL,},[HDF_OBJECT_ID_DRIVER_LOADER] ={.Create = HdfDriverLoaderCreate,.Release = NULL,},[HDF_OBJECT_ID_DEVICE] ={.Create = HdfDeviceCreate,.Release = HdfDeviceRelease,},[HDF_OBJECT_ID_DEVICE_TOKEN] ={.Create = HdfDeviceTokenCreate,.Release = HdfDeviceTokenRelease,},[HDF_OBJECT_ID_DEVICE_SERVICE] ={.Create = DeviceNodeExtCreate,.Release = DeviceNodeExtRelease,}
};

触发函数指针Create 即执行DevmgrServiceCreate 给IDevmgrService结构体指针函数赋值后再返回。

bool DevmgrServiceConstruct(struct DevmgrService *inst)
{struct IDevmgrService *devMgrSvcIf = NULL;...devMgrSvcIf = (struct IDevmgrService *)inst;if (devMgrSvcIf != NULL) {devMgrSvcIf->AttachDevice = DevmgrServiceAttachDevice;devMgrSvcIf->DetachDevice = DevmgrServiceDetachDevice;devMgrSvcIf->LoadDevice = DevmgrServiceLoadDevice;devMgrSvcIf->UnloadDevice = DevmgrServiceUnloadDevice;devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;devMgrSvcIf->StartService = DevmgrServiceStartService;devMgrSvcIf->PowerStateChange = DevmgrServicePowerStateChange;devMgrSvcIf->ListAllDevice = DevmgrServiceListAllDevice;DListHeadInit(&inst->hosts);return true;} else {return false;}
}

2、IDevmgrService#StartService(instance)——>drivers/hdf_core/framework/core/manager/src/devmgr_service.c#DevmgrServiceStartService

int DevmgrServiceStartService(struct IDevmgrService *inst)
{int ret;struct DevmgrService *dmService = (struct DevmgrService *)inst;...ret = DevSvcManagerStartService();HDF_LOGI("start svcmgr result %{public}d", ret);return DevmgrServiceStartDeviceHosts(dmService);
}

2.1、DevSvcManagerStartService()

DevSvcManagerGetInstance——>HdfObjectManagerGetObject——>HdfObjectManagerGetCreators——>根据objectId去HdfObjectCreator数组中去获取对应的指针,并触发Create函数指针

drivers/hdf_core/framework/core/manager/src/devmgr_service.c

int DevSvcManagerStartService(void)
{int ret;struct IDevSvcManager *svcmgr = DevSvcManagerGetInstance();if (svcmgr->StartService == NULL) {return HDF_SUCCESS;}//触发DevSvcManagerStubStartret = svcmgr->StartService(svcmgr);if (ret != HDF_SUCCESS) {HDF_LOGE("failed to start service manager");}return ret;
}

和上面类似先是执行Create 函数指针即DevSvcManagerStubCreate,并给StartService函数指针赋值

struct HdfObject *DevSvcManagerStubCreate(void)
{static struct DevSvcManagerStub *instance;instance = OsalMemCalloc(sizeof(struct DevSvcManagerStub));if (!DevSvcManagerStubConstruct(instance)) {OsalMemFree(instance);instance = NULL;}return (struct HdfObject *)instance;
}
static bool DevSvcManagerStubConstruct(struct DevSvcManagerStub *inst)
{...//给IDevSvcManager 的函数指针赋值if (!DevSvcManagerConstruct(&inst->super)) {HDF_LOGE("failed to construct device service manager");return false;}inst->super.super.StartService = DevSvcManagerStubStart;OsalMutexInit(&inst->devSvcStubMutex);HdfSListInit(&inst->devObjHolderList);return true;
}执行了上面后IDevSvcManager的函数指针StartService被赋值为DevSvcManagerStubStart并随即执行,用于注册到HDF和IPC相关的。
●HdfRemoteDispatcher 的Dispatch 函数指针被赋值为DevSvcManagerStubDispatch
●给DevSvcManagerStub的remote 对象赋值为远端代理对象以及监听远端代理对象死亡时间
●执行注册
drivers/hdf_core/adapter/uhdf2/manager/src/devsvc_manager_stub.c
int DevSvcManagerStubStart(struct IDevSvcManager *svcmgr)
{struct DevSvcManagerStub *inst = (struct DevSvcManagerStub *)svcmgr;...ServStatListenerHolderinit();...//后面IPC时会用到static struct HdfRemoteDispatcher dispatcher = {.Dispatch = DevSvcManagerStubDispatch};inst->remote = HdfRemoteServiceObtain((struct HdfObject *)inst, &dispatcher);if (inst->remote == NULL) {HDF_LOGE("failed to obtain device service manager remote service");return HDF_ERR_MALLOC_FAIL;}if (!HdfRemoteServiceSetInterfaceDesc(inst->remote, "HDI.IServiceManager.V1_0")) {HDF_LOGE("%{public}s: failed to init interface desc", __func__);HdfRemoteServiceRecycle(inst->remote);return HDF_ERR_INVALID_OBJECT;}inst->recipient.OnRemoteDied = DevSvcManagerOnServiceDied;//注册并发布int ret = HdfRemoteServiceRegister(DEVICE_SERVICE_MANAGER_SA_ID, inst->remote);if (ret != 0) {HDF_LOGE("failed to publish device service manager, %{public}d", ret);HdfRemoteServiceRecycle(inst->remote);inst->remote = NULL;} else {HDF_LOGI("publish device service manager success");inst->started = true;}return ret;
}

执行注册
drivers/hdf_core/adapter/uhdf2/ipc/src/hdf_remote_service.c

int HdfRemoteServiceRegister(int32_t serviceId, struct HdfRemoteService *service)
{return HdfRemoteAdapterAddSa(serviceId, service);
}int HdfRemoteAdapterAddSa(int32_t saId, struct HdfRemoteService *service)
{...auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();const int32_t waitTimes = 50;const int32_t sleepInterval = 20000;int32_t timeout = waitTimes;while (saManager == nullptr && (timeout > 0)) {HDF_LOGI("waiting for samgr...");usleep(sleepInterval);saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();timeout--;}struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);int ret = saManager->AddSystemAbility(saId, holder->remote_);(void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);HDF_LOGI("add sa %{public}d, ret = %{public}s", saId, (ret == 0) ? "succ" : "fail");...return HDF_SUCCESS;
}

原来注册、发布的对象都是SA,接下来就是SA相关的管理逻辑了。

2.2、DevmgrServiceStartDeviceHosts

static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst)
{int ret;struct HdfSList hostList;struct HdfSListIterator it;struct HdfHostInfo *hostAttr = NULL;HdfSListInit(&hostList);if (!HdfAttributeManagerGetHostList(&hostList)) {HDF_LOGW("%s: host list is null", __func__);return HDF_SUCCESS;}HdfSListIteratorInit(&it, &hostList);while (HdfSListIteratorHasNext(&it)) {hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it);ret = DevmgrServiceStartDeviceHost(inst, hostAttr);if (ret != HDF_SUCCESS) {HDF_LOGW("%{public}s failed to start device host, host id is %{public}u, host name is '%{public}s'",__func__, hostAttr->hostId, hostAttr->hostName);}}HdfSListFlush(&hostList, HdfHostInfoDelete);return HDF_SUCCESS;
}

然后DevmgrServiceStartHostProcess 里通过IDriverInstaller 启动StartDeviceHost,即执行DriverInstallerFullStartDeviceHost

static int DevmgrServiceStartHostProcess(struct DevHostServiceClnt *hostClnt, bool sync, bool dynamic)
{HDF_LOGE("NNRT#DevmgrServiceStartHostProcess ");int waitCount = WAIT_HOST_SLEEP_CNT;struct IDriverInstaller *installer = DriverInstallerGetInstance();if (installer == NULL || installer->StartDeviceHost == NULL) {HDF_LOGE("invalid installer");return HDF_FAILURE;}hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName, dynamic);if (hostClnt->hostPid == HDF_FAILURE) {HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);return HDF_FAILURE;}hostClnt->stopFlag = false;if (!sync) {return HDF_SUCCESS;}while (hostClnt->hostService == NULL && waitCount > 0) {OsalMSleep(WAIT_HOST_SLEEP_TIME);waitCount--;}if (waitCount <= 0) {HDF_LOGE("wait host(%{public}s, %{public}d) attach timeout", hostClnt->hostName, hostClnt->hostId);hostClnt->hostPid = -1;return HDF_ERR_TIMEOUT;}return HDF_SUCCESS;
}

然后installer->StartDeviceHost

int DriverInstallerFullStartDeviceHost(uint32_t devHostId, const char* devHostName, bool dynamic)
{if (dynamic) {int ret = ServiceControlWithExtra(devHostName, START, NULL, 0);HDF_LOGD("%{public}s %{public}s %{public}d %{public}d", __func__, devHostName, devHostId, ret);}return HDF_SUCCESS;
}

在base/startup/init/interfaces/innerkits/service_control/service_control.c#ServiceControlWithExtra里真正开始启动进程

int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc)
{BEGET_ERROR_CHECK(serviceName != NULL, return -1, "Service name is null.");int ret = 0;switch (action) {case START:ret = StartProcess(serviceName, extArgv, extArgc);break;case STOP:ret = StopProcess(serviceName);break;case RESTART:ret = RestartProcess(serviceName, extArgv, extArgc);break;default:BEGET_LOGE("Set service %s action %d error", serviceName, action);ret = -1;break;}return ret;
}

未完待续…

相关文章:

鸿蒙进阶——驱动框架UHDF 机制核心源码解读(一)

文章大纲 引言一、uhdf 概述二、uhdf 的核心参与角色1、drivers/hdf_core/adapter/uhdf2/manager/device_manager.c1.1、drivers/hdf_core/framework/core/manager/src/devmgr_service.c#DevmgrServiceGetInstance通过objectId获取IDevmgrService实例1.2、drivers/hdf_core/fra…...

【C/C++】探索单例模式:线程安全与性能优化

文章目录 Singleton1 指针版本Version 1 非线程安全版本Version 2 加锁版本Version 3.1 双重检查锁版本 AtomicMutexVersion 3.2 双重检查锁版本 Atomic-onlyVersion 3 两种方式对比 2 引用版本Version 1 简单版本 不推荐Version 2 初始化安全版本Version 3 初始化操作安全版本…...

Windows安装MongoDb.并使用.NET 9连接

以下是在 Windows 系统上安装 MongoDB 的详细步骤&#xff1a; 方法一&#xff1a;通过安装向导 下载安装包 访问官网下载页&#xff1a;https://www.mongodb.com/try/download/community选择版本&#xff1a; Version&#xff1a;推荐最新稳定版&#xff08;如 8.09&#xff0…...

React深度解析:Hooks体系与Redux Toolkit现代状态管理实践

前言 React作为当今最流行的前端框架之一&#xff0c;其生态体系不断演进&#xff0c;为开发者提供了更高效、更优雅的解决方案。本文将深入探讨React的两大核心主题&#xff1a;Hooks体系&#xff08;特别是useState和useEffect&#xff09;以及Redux Toolkit现代状态管理方案…...

【Linux安装与维护】

文章目录 一、实验目的二、实验环境三、实验内容3.1 Red Hat系统安装3.2 硬盘分区与挂载3.3 root密码恢复 四、总结4.1 问题与解决4.2 实验收获 一、实验目的 熟练掌握Red Hat Enterprise Linux 8.x/9.0系统的安装流程&#xff0c;包括虚拟机配置、自定义分区和软件选择。学会…...

具有思考模式模型部署:Qwen3、DeepSeek-R1-Distill、Phi-4、QWQ系列

文章目录 1 介绍 Qwen3、DeepSeek-R1-Distill、Phi-4、QWQ2 部署 Qwen3、DeepSeek-R1-Distill、Phi-4、QWQ3 模型运行 Qwen3、DeepSeek-R1-Distill、Phi-4、QWQ4 结果Qwen3-0.6BDeepSeek-R1-Distill-Qwen-1.5BPhi-4-mini-reasoning 平台采用Autodl&#xff1a;https://www.auto…...

Mac安装redis

1、 去往网址 http://​编download.​编redis.io/releases/ 找到任意 结尾为* .tar.gz的文件下载下来 2、使用终端进入下载下来的redis文件 3、直接执行redis-server 如果出现redis标志性的图代表成功 如果显示command not found :redis-server 则在终端再进入src文件夹下&…...

python-leetcode 71.每日温度

题目&#xff1a; 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 可以理…...

[250521] DBeaver 25.0.5 发布:SQL 编辑器、导航器全面升级,新增 Kingbase 支持!

目录 DBeaver 25.0.5 发布&#xff1a;SQL 编辑器、导航器全面升级&#xff0c;新增 Kingbase 支持&#xff01; DBeaver 25.0.5 发布&#xff1a;SQL 编辑器、导航器全面升级&#xff0c;新增 Kingbase 支持&#xff01; 近日&#xff0c;DBeaver 发布了 25.0.5 版本&#xf…...

Java枚举详解

文章目录 1. 引言1.1 什么是枚举1.2 为什么需要枚举1.3 枚举的优势 2. 枚举基础2.1 枚举的声明与使用基本声明在类中定义枚举枚举的基本使用 2.2 枚举的常用方法1. values()2. valueOf(String name)3. name()4. ordinal()5. toString()6. compareTo(E o)7. equals(Object other…...

Android13 wifi设置国家码详解

Android13 wifi设置国家码详解 文章目录 Android13 wifi设置国家码详解一、前言二、设置wifi国家码相关代码1、adb或者串口也能设置和获取当前国家码&#xff08;1&#xff09;查询命令的方式&#xff08;2&#xff09;获取和设置国家码的示例 2、Java代码设置国家码3、获取当前…...

Docker安装MinIO对象存储中间件

MinIO 是一个高性能、分布式的对象存储系统&#xff0c;兼容 Amazon S3 云存储服务协议&#xff0c;广泛应用于企业存储、大数据、机器学习和容器化应用等领域。以下是详细介绍&#xff1a; 核心特点 兼容 S3 API &#xff1a;全面兼容 Amazon S3 API&#xff0c;这意味着使用…...

EasyPan 使用及功能优化

文章目录 在线体验为什么我想做这个&#xff1f;kiftd网盘EasyPan EasyPan 客制化&#xff0c;升级为 RokiPan登录界面主界面分享 上传&下载速度测试下载上传 个人优化&#xff08;部分截图&#xff09;&#xff1a;已实现功能汇总&#xff08;原版 优化 &#xff09;待实…...

word通配符表

目录 一、word查找栏代码&通配符一览表二、word替换栏代码&通配符一览表三、参考文献 一、word查找栏代码&通配符一览表 序号清除使用通配符复选框勾选使用通配符复选框特殊字符代码特殊字符代码or通配符1任意单个字符^?一个任意字符?2任意数字^#任意数字&#…...

word格式相关问题

页眉 1 去除页眉横线&#xff1a; 双击打开页眉&#xff0c;然后点击正文样式&#xff0c;横线就没有了。 2 让两部分内容的页眉不一样&#xff1a; 使用“分节符”区分两部分内容&#xff0c;分节符可以在“布局-分隔符”找到。然后双击打开页眉&#xff0c;取消“链接到前一…...

springboot使用xdoc-report包导出word

背景&#xff1a;项目需要使用xdoc-report.jar根据设置好的word模版&#xff0c;自动填入数据 导出word 框架使用 我的需求是我做一个模板然后往里面填充内容就导出我想要的word文件&#xff0c;问了下chatgpt还有百度&#xff0c;最后选用了xdocreport这个框架&#xff0c;主…...

电脑中所有word文件图标变白怎么恢复

电脑中的word文件图标变白&#xff0c;如下图所示&#xff1a; 解决方法&#xff1a; 1.winR-->在弹出的运行窗口中输入“regedit”(如下图所示)&#xff0c;点击确定&#xff1a; 2.按照路径“计算机\HKEY_CLASSES_ROOT\Word.Document.12\DefaultIcon”去找到“&#xff0…...

node.js如何实现双 Token + Cookie 存储 + 无感刷新机制

node.js如何实现双 Token Cookie 存储 无感刷新机制 为什么要实施双token机制&#xff1f; 优点描述安全性Access Token 短期有效&#xff0c;降低泄露风险&#xff1b;Refresh Token 权限受限&#xff0c;仅用于获取新 Token用户体验用户无需频繁重新登录&#xff0c;Toke…...

如何从 iPhone 获取照片:5 个有效解决方案

有时&#xff0c;我们在 iPhone 上积累了太多照片&#xff0c;因此有必要从 iPhone 上删除照片。无论您的设备需要更多空间&#xff0c;还是只是想备份珍贵的记忆以妥善保管&#xff0c;您都可以找到从 iPhone 上拍摄照片的有效方法。您可以选择完成任务的最佳方式。 第 1 部分…...

大模型知识

############################################################## 一、vllm大模型测试参数和原理 tempreature top_p top_k ############################################################## tempreature top_p top_k 作用&#xff1a;总体是控制模型的发散程度、多样…...

微软正式发布 SQL Server 2025 公开预览版,深度集成AI功能

微软在今年的 Build 2025 大会上正式发布了 SQL Server 2025 公开预览版&#xff0c;标志着这一经典数据库产品在 AI 集成、安全性、性能及开发者工具方面的全面升级。 AI 深度集成与创新 原生向量搜索&#xff1a;SQL Server 2025 首次将 AI 功能直接嵌入数据库引擎&#xff…...

git中,给分支打标签

1.创建标签 标签可以是轻量级标签或带注释的标签两种 轻量级标签 git tag <tag-name> 带注释的标签 git tag -a <tag-name> -m "标签信息" 2.查看标签 git tag 查看标签详细信息 git show <tag-name> 3.推送标签到远程仓库 推送指定标签…...

微软 Build 2025:开启 AI 智能体时代的产业革命

在 2025 年 5 月 19 日的微软 Build 开发者大会上&#xff0c;萨提亚・纳德拉以 "我们已进入 AI 智能体时代" 的宣言&#xff0c;正式拉开了人工智能发展的新纪元。这场汇聚了奥特曼、黄仁勋、马斯克三位科技领袖的盛会&#xff0c;不仅发布了 50 余项创新产品&#…...

k8s面试题-ingress

场景&#xff1a;我通过deployment更新pod&#xff0c;ingress是怎么把新的请求流量发送到我新的pod的&#xff1f;是怎么监控到我更新的pod的&#xff1f; 在 Kubernetes 中&#xff0c;Ingress 是一种 API 对象&#xff0c;用于管理外部访问到集群内服务的 HTTP 和 HTTPS 路…...

时间序列预测的迁移学习

在本文中&#xff0c;我们将了解如何将迁移学习应用于时间序列预测&#xff0c;以及如何在多样化的时间序列数据集上训练一次预测模型&#xff0c;之后无需训练即可在不同数据集上进行预测。我们将使用开源 Darts 库&#xff0c;仅用几行代码即可完成所有这些操作。你可以点击此…...

react中运行 npm run dev 报错,提示vite.config.js出现错误 @esbuild/win32-x64

在React项目中运行npm run dev时&#xff0c;如果遇到vite.config.js报错&#xff0c;提示esbuild/win32-x64在另一个平台中被使用&#xff0c;通常是由于依赖冲突或缓存问题导致的。解决方法是删除node_modules文件夹&#xff0c;并重新安装依赖。 如下图&#xff1a; 解决办…...

量子计算模拟:从理论到实践

量子计算作为现代物理学与计算机科学的前沿交叉领域&#xff0c;正逐渐从纯理论研究走向实际应用。本文将介绍一个基于Python的量子计算模拟框架&#xff0c;重点探讨量子比特、量子门操作以及量子态的演化等核心概念&#xff0c;并通过可视化手段直观展示量子态的特性。 量子…...

143.重排链表的尝试

listnode* p0cur,cur->nextq;p0->next有没有改变 ChatGLM 让我们逐步分析这段代码&#xff0c;看看 p0->next 是否发生了改变。 假设我们有一个链表&#xff0c;cur 是当前节点&#xff0c;q 是另一个节点。代码如下&#xff1a; 代码生成完成 C代码 首先&#…...

精准识别记忆细胞!Elabscience PE Anti-Human/Mouse CD44 抗原特异性抗体

概述 CD44 是一种广泛表达的细胞表面黏附分子&#xff0c;参与细胞迁移、炎症反应及肿瘤转移等关键生物学过程。Elabscience 推出的PE Anti-Human/Mouse CD44 Antibody [IM7]&#xff08;货号&#xff1a;E-AB-F1100D&#xff09;是一款高特异性、高灵敏度的流式抗体&#xff…...

OpenCV CUDA模块特征检测与描述------一种基于快速特征点检测和旋转不变的二进制描述符类cv::cuda::ORB

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::ORB 是 OpenCV 库中 CUDA 模块的一部分&#xff0c;它提供了一种基于快速特征点检测和旋转不变的二进制描述符的方法&#xff0c;用于…...

OpenCV CUDA模块特征检测与描述------创建一个 盒式滤波器(Box Filter)函数createBoxFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::createBoxFilter 是 OpenCV CUDA 模块中的一个工厂函数&#xff0c;用于创建一个 盒式滤波器&#xff08;Box Filter&#xff09;&…...

【八股战神篇】Spring高频面试题汇总

专栏简介 Bean 的生命周期了解么? 延伸 谈谈自己对于 Spring IoC 的了解 延伸 什么是动态代理? 延伸 动态代理和静态代理的区别 延伸 Spring AOP的执行流程 延伸 Spring的事务什么情况下会失效? 延伸 专栏简介 八股战神篇专栏是基于各平台共上千篇面经,上万道…...

高阶数据结构——红黑树实现

目录 1.红黑树的概念 1.1 红黑树的规则&#xff1a; 1.2 红黑树的效率 2.红黑树的实现 2.1 红黑树的结构 2.2 红黑树的插入 2.2.1 不旋转只变色&#xff08;无论c是p的左还是右&#xff0c;p是g的左还是右&#xff0c;都是一样的变色处理方式&#xff09; 2.2.2 单旋变色…...

java综合交易所13国语言,股票,区块链,外汇,自带客服系统运营级,有测试

这套pc和H5是一体的&#xff0c;支持测试&#xff0c;目前只有外汇和区块链&#xff0c;某站居然有人卖3.8w&#xff0c;还觉得自己这个价格很好 自带客服系统&#xff0c;虽然是老的&#xff0c;但是可玩性还是很高的&#xff0c;也支持c2c&#xff0c;理财&#xff0c;质押&a…...

六:操作系统虚拟内存之缺页中断

深入理解操作系统&#xff1a;缺页中断 (Page Fault) 的处理流程 在上一篇文章中&#xff0c;我们介绍了虚拟内存和按需调页 (Demand Paging) 的概念。虚拟内存为每个进程提供了巨大的、独立的虚拟地址空间&#xff0c;并通过页表 (Page Table) 将虚拟页面 (Virtual Page) 映射…...

iOS 15.4.1 TrollStore(巨魔商店)安装教程详解:第二篇

&#x1f680; iOS 15.4.1 TrollStore&#xff08;巨魔商店&#xff09;安装教程详解 ✨ 前言&#x1f6e0;️ 如何安装 TrollStore&#xff1f;第一步&#xff1a;打开 Safari 浏览器第二步&#xff1a;选择对应系统版本安装方式第三步&#xff1a;访问地址&#xff0c;下载配…...

【JAVA】比较器Comparator与自然排序(28)

JAVA 核心知识点详细解释 Java中比较器Comparator的概念和使用方法 概念 Comparator 是 Java 中的一个函数式接口,位于 java.util 包下。它用于定义对象之间的比较规则,允许我们根据自定义的逻辑对对象进行排序。与对象的自然排序(实现 Comparable 接口)不同,Comparat…...

bitbar环境搭建(ruby 2.4 + rails 5.0.2)

此博客为武汉大学WA学院网络安全课程&#xff0c;理论课大作业Web环境搭建。 博主搭了2天&#xff01;&#xff01;&#xff01;血泪教训是还是不能太相信ppt上的教程。 一开始尝试了ppt上的教程&#xff0c;然后又转而寻找网络资源 cs155源代码和docker配置&#xff0c;做到…...

Spring Boot接口通用返回值设计与实现最佳实践

一、核心返回值模型设计&#xff08;增强版&#xff09; package com.chat.common;import com.chat.util.I18nUtil; import com.chat.util.TraceUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Getter;import java.io.Serializable;/*** 功能: 通…...

线上 Linux 环境 MySQL 磁盘 IO 高负载深度排查与性能优化实战

目录 一、线上告警 二、问题诊断 1. 系统层面排查 2. 数据库层面分析 三、参数调优 1. sync_binlog 参数优化 2. innodb_flush_log_at_trx_commit 参数调整 四、其他优化建议 1. 日志文件位置调整 2. 生产环境核心参数配置模板 3. 突发 IO 高负载应急响应方案 五、…...

React--函数组件和类组件

React 中的函数组件和类组件是两种定义组件的方式&#xff0c;它们有以下主要区别&#xff1a; 1. 语法与定义方式 函数组件&#xff1a; 是 JavaScript 函数&#xff0c;接收 props 作为参数&#xff0c;返回 JSX。 const MyComponent (props) > {return <div>Hell…...

GitHub 趋势日报 (2025年05月20日)

本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1virattt/ai-hedge-fundAI对冲基金团队⭐ 1781⭐ 31163Python2public-apis/pub…...

uni.getLocation()和uni.openSetting()

文章目录 环境背景问题分析问题1问题2 uni.getLocation()和uni.openSetting()的区别和联系其它uni.getLocation()的failuni.openSetting()的authSetting对象 参考 环境 Windows 11 专业版HBuilder X 4.65微信开发者工具 Stable 1.06.2412050 背景 在小程序开发中&#xff0c…...

医疗行业数据共享新实践:如何用QuickAPI打通诊疗全流程数据壁垒

在医疗行业&#xff0c;数据的高效流转直接影响诊疗效率和患者体验。某三甲医院在数字化转型中发现&#xff0c;虽然已积累大量核心业务数据&#xff0c;但各科室系统间的数据互通仍存在明显瓶颈——检验科的报告无法实时同步至门诊系统&#xff0c;药房库存数据与采购系统脱节…...

管理会议最佳实践:高效协同与价值最大化

1.会前准备:明确目标与计划 1.1 明确会议目的 1.1.1 必要性评估 开会前需自问是否真的需要开会,若问题可通过邮件、文档或异步沟通解决,则应避免开会,以节省时间和资源。 1.1.2 目标定义 清晰定义会议目标,如决策、信息同步、创意讨论等,并提前告知参与者,使大家明确参…...

万物智联,重塑未来:鸿蒙操作系统的实战突破与生态崛起

鸿蒙操作系统&#xff08;HarmonyOS&#xff09;作为华为自主研发的分布式操作系统&#xff0c;自2019年发布以来&#xff0c;已从技术探索迈入大规模商用阶段。截至2025年&#xff0c;鸿蒙系统不仅成为全球第二大移动操作系统&#xff0c;更在政企数字化、工业制造、金融科技等…...

人工智能路径:技术演进下的职业发展导航

当生成式AI能够自主完成创意设计、商业分析和代码编写时&#xff0c;职业发展的传统路径正在被重新测绘。人工智能路径不再是一条预设的直线&#xff0c;而演变为包含多重可能性的动态网络——未来的职业成功&#xff0c;将取决于在技术变革中持续定位自身价值节点的能力。 一…...

深入理解Java虚拟机之垃圾收集器篇(垃圾回收器的深入解析待完成TODO)

目录 **一. 如何判断对象的存亡**引用计数算法:可达性分析算法: **二. Java中的四种引用****三. 垃圾回收算法****1. 标记 - 清除算法****2. 标记 - 复制算法****3. 标记 - 整理算法****4. 分代收集理论**(了解即可) **四. 十种主流垃圾收集器****3.1 Serial 收集器****3.2 Par…...

牛客网 NC16407 题解:托米航空公司的座位安排问题

牛客网 NC16407 题解&#xff1a;托米航空公司的座位安排问题 题目分析 解题思路 本题可以采用深度优先搜索(DFS)来解决&#xff1a; 从左上角开始&#xff0c;按行优先顺序遍历每个座位对于每个座位&#xff0c;有两种选择&#xff1a; 选择该座位&#xff08;如果满足条件…...

拉普拉斯高斯(LoG)滤波器掩模的注意事项

目录 问题&#xff1a; 解答&#xff1a; 一、高斯函数归一化&#xff1a;消除幅度偏差 1. 归一化的定义 2. 为何必须归一化&#xff1f; 二、拉普拉斯系数和为零&#xff1a;抑制直流项干扰 1. 拉普拉斯算子的特性 2. 系数和不为零的后果 三、直流项如何影响零交叉点&…...