OpenHarmony平台驱动开发(二),CLOCK
OpenHarmony平台驱动开发(二)
CLOCK
概述
功能简介
CLOCK,时钟是系统各个部件运行的基础,以CPU时钟举例,CPU 时钟是指 CPU 内部的时钟发生器,它以频率的形式工作,用来同步和控制 CPU 内部的各个操作。
基本概念
设备的时钟信号是指在电子设备中用于同步和控制各个模块或组件操作的信号。它是设备内部的一个基本信号源,用于确保设备的正常运行和数据传输的准确性。
运作机制
在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。CLOCK模块即采用统一服务模式(如图1所示)。
CLOCK模块各分层的作用为:
-
接口层:提供打开设备,写入数据,关闭设备的能力。
-
核心层:主要负责服务绑定、初始化以及释放管理器,并提供添加、删除以及获取控制器的能力。
-
适配层:由驱动适配者实现与硬件相关的具体功能,如控制器的初始化等。
在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。
使用指导
场景介绍
CLOCK提供芯片级别的时钟管理:时钟功能可用于控制芯片内部的时钟分频、时钟倍频、时钟源选择和时钟门控等操作。通过合理的时钟管理,可以提高芯片的能效,并确保各个功能部件的正确协调和协同工作。
接口说明
为了保证上层在调用CLOCK接口时能够正确的操作硬件,核心层在//drivers/hdf_core/framework/support/platform/include/clock/clock_core.h中定义了以下钩子函数。驱动适配者需要在适配层实现这些函数的具体功能,并与这些钩子函数挂接,从而完成接口层与核心层的交互。
ClockMethod和ClockLockMethod定义:
struct ClockMethod {int32_t (*start)(struct ClockDevice *device);int32_t (*stop)(struct ClockDevice *device);int32_t (*setRate)(struct ClockDevice *device, uint32_t rate);int32_t (*getRate)(struct ClockDevice *device, uint32_t *rate);int32_t (*disable)(struct ClockDevice *device);int32_t (*enable)(struct ClockDevice *device);struct ClockDevice *(*getParent)(struct ClockDevice *device);int32_t (*setParent)(struct ClockDevice *device, struct ClockDevice *parent);
};struct ClockLockMethod {int32_t (*lock)(struct ClockDevice *device);void (*unlock)(struct ClockDevice *device);
};
在适配层中,ClockMethod必须被实现,ClockLockMethod可根据实际情况考虑是否实现。核心层提供了默认的ClockLockMethod,其中使用Spinlock作为保护临界区的锁:
static int32_t ClockDeviceLockDefault(struct ClockDevice *device)
{if (device == NULL) {HDF_LOGE("ClockDeviceLockDefault: device is null!");return HDF_ERR_INVALID_OBJECT;}return OsalSpinLock(&device->spin);
}static void ClockDeviceUnlockDefault(struct ClockDevice *device)
{if (device == NULL) {HDF_LOGE("ClockDeviceUnlockDefault: device is null!");return;}(void)OsalSpinUnlock(&device->spin);
}static const struct ClockLockMethod g_clockLockOpsDefault = {.lock = ClockDeviceLockDefault,.unlock = ClockDeviceUnlockDefault,
};
若实际情况不允许使用Spinlock,驱动适配者可以考虑使用其他类型的锁来实现一个自定义的ClockLockMethod。一旦实现了自定义的ClockLockMethod,默认的ClockLockMethod将被覆盖。
表 1 ClockMethod结构体成员的钩子函数功能说明
函数成员 | 入参 | 出参 | 返回值 | 功能 |
---|---|---|---|---|
start | device:结构体指针,核心层CLOCK控制器 | 无 | HDF_STATUS相关状态 | 打开CLOCK设备 |
stop | device:结构体指针,核心层CLOCK控制器 | 无 | HDF_STATUS相关状态 | 关闭CLOCK设备 |
setRate | device:结构体指针,核心层CLOCK控制器 | 无 | HDF_STATUS相关状态 | 设置CLOCK设备的速率 |
getRate | device:结构体指针,核心层CLOCK控制器 | 获取的速率 | HDF_STATUS相关状态 | 获取CLOCK设备的速率 |
disable | device:结构体指针,核心层CLOCK控制器 | 无 | HDF_STATUS相关状态 | 使能CLOCK设备 |
enable | device:结构体指针,核心层CLOCK控制器 | 无 | HDF_STATUS相关状态 | 去使能CLOCK设备 |
getParent | device:结构体指针,核心层CLOCK控制器 | 获取的device:结构体指针,核心层CLOCK控制器 | HDF_STATUS相关状态 | 设置CLOCK设备的父设备 |
setParent | device:结构体指针,核心层CLOCK控制器 | 无 | HDF_STATUS相关状态 | 设置CLOCK设备的父设备 |
表 2 ClockLockMethod结构体成员函数功能说明
函数成员 | 入参 | 出参 | 返回值 | 功能 |
---|---|---|---|---|
lock | device:结构体指针,核心层CLOCK设备对象。 | 无 | HDF_STATUS相关状态 | 获取临界区锁 |
unlock | device:结构体指针,核心层CLOCK设备对象。 | 无 | HDF_STATUS相关状态 | 释放临界区锁 |
开发步骤
CLOCK模块适配包含以下四个步骤:
-
实例化驱动入口
-
实例化HdfDriverEntry结构体成员。
-
调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。
-
-
配置属性文件
-
在device_info.hcs文件中添加deviceNode描述。
-
【可选】添加clock_config.hcs器件属性文件。
-
-
实例化核心层接口函数
-
初始化ClockDevice成员。
-
实例化ClockDevice成员ClockMethod。
说明:
实例化ClockDevice成员ClockMethod,其定义和成员说明见接口说明。
-
-
驱动调试
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的测试用例是否成功等。
开发实例
下方将基于RK3568开发板以//drivers/hdf_core/adapter/khdf/linux/platform/clock/clock_adapter.c驱动为示例,展示需要驱动适配者提供哪些内容来完整实现设备功能。
-
实例化驱动入口
驱动入口必须为HdfDriverEntry(在//drivers/hdf_core/interfaces/inner_api/host/shared/hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。
一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
CLOCK驱动入口参考:
CLOCK控制器会出现多个设备挂接的情况,因而在HDF框架中首先会为此类型的设备创建一个管理器对象。这样,需要打开某个设备时,管理器对象会根据指定参数查找到指定设备。
CLOCK管理器的驱动由核心层实现,驱动适配者不需要关注这部分内容的实现,但在实现Init函数的时候需要调用核心层的ClockDeviceAdd函数,它会实现相应功能。
struct HdfDriverEntry g_clockLinuxDriverEntry = {.moduleVersion = 1,.Bind = NULL,.Init = LinuxClockInit,.Release = LinuxClockRelease,.moduleName = "linux_clock_adapter", // 【必要且与device_info.hcs文件内的模块名匹配】 }; HDF_INIT(g_clockLinuxDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中// 核心层clock_core.c管理器服务的驱动入口 struct HdfDriverEntry g_clockManagerEntry = {.moduleVersion = 1,.Bind = ClockManagerBind, // CLOCK不需要实现Bind,本例是一个空实现,驱动适配者可根据自身需要添加相关操作.Init = ClockManagerInit, // 见Init参考.Release = ClockManagerRelease, // 见Release参考.moduleName = "HDF_PLATFORM_CLOCK_MANAGER", // 这与device_info.hcs文件中device0对应 }; HDF_INIT(g_clockManagerEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中
-
配置属性文件
完成驱动入口注册之后,下一步请在//vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs文件中添加deviceNode信息,并在clock_config.hcs中配置器件属性。
deviceNode信息与驱动入口注册相关,器件属性值对于驱动适配者的驱动实现以及核心层ClockDevice相关成员的默认值或限制范围有密切关系。
统一服务模式的特点是device_info.hcs文件中第一个设备节点必须为CLOCK管理器,其各项参数如表3所示:
表 3 device_info.hcs节点参数说明
成员名 值 policy 驱动服务发布的策略,CLOCK管理器具体配置为2,表示驱动对内核态和用户态都发布服务 priority 驱动启动优先级(0-200),值越大优先级越低。CLOCK管理器具体配置为59 permission 驱动创建设备节点权限,CLOCK管理器具体配置为0664 moduleName 驱动名称,CLOCK管理器固定为HDF_PLATFORM_CLOCK_MANAGER serviceName 驱动对外发布服务的名称,CLOCK管理器服务名设置为HDF_PLATFORM_CLOCK_MANAGER deviceMatchAttr 驱动私有数据匹配的关键字,CLOCK管理器没有使用,可忽略 从第二个节点开始配置具体CLOCK控制器信息,第一个节点并不表示某一路CLOCK控制器,而是代表一个资源性质设备,用于描述一类CLOCK控制器的信息。本例只有一个CLOCK设备,如有多个设备,则需要在device_info.hcs文件增加deviceNode信息,以及在clock_config.hcs文件中增加对应的器件属性。
-
device_info.hcs配置参考
root {device_info {platform :: host {device_clock :: device {device0 :: deviceNode {policy = 2;priority = 59;permission = 0644;moduleName = "HDF_PLATFORM_CLOCK_MANAGER";serviceName = "HDF_PLATFORM_CLOCK_MANAGER";}device1 :: deviceNode {policy = 0; // 等于0,不需要发布服务。priority = 65; // 驱动启动优先级。permission = 0644; // 驱动创建设备节点权限。moduleName = "linux_clock_adapter"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致。deviceMatchAttr = "linux_clock_adapter_0"; //【必要】用于配置控制器私有数据,要与clock_config.hcs中对应控制器保持一致,具体的控制器信息在clock_config.hcs中。}}}} }
-
clock_config.hcs配置参考
此处以RK3568为例,给出HCS配置参考。
root {platform {clock_config {match_attr = "linux_clock_adapter_0";template clock_device {}device_clock_0x0000 :: clock_device {deviceName = "/cpus/cpu@0";deviceIndex = 1;}}} }
需要注意的是,新增clock_config.hcs配置文件后,必须在hdf.hcs文件中将其包含,否则配置文件无法生效。
例如:本例中clock_config.hcs所在路径为//vendor/hihope/rk3568/hdf_config/ hdf_config/khdf/hdf.hcs,则必须在产品对应的hdf.hcs中添加如下语句:
#include "platform/clock_config_linux.hcs" // 配置文件相对路径
本例基于RK3568开发板的标准系统Linux内核运行,对应的hdf.hcs文件路径为//vendor/hihope/rk3568/hdf_config/ hdf_config/khdf/hdf.hcs驱动适配者需根据实际情况选择对应路径下的文件进行修改。
-
-
实例化核心层函数
完成驱动入口注册之后,下一步就是以核心层ClockDevice对象的初始化为核心,包括初始化驱动适配者自定义结构体(传递参数和数据),实例化ClockDevice成员ClockMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。
-
自定义结构体参考。
从驱动的角度看,自定义结构体是参数和数据的载体,而且clock_config.hcs文件中的数值会被HDF读入并通过DeviceResourceIface来初始化结构体成员,其中一些重要数值(例如设备号、总线号等)也会传递给核心层ClockDevice对象。
// ClockDevice是核心层控制器结构体,其中的成员在Init函数中会被赋值。 struct ClockDevice {const struct ClockMethod *ops;OsalSpinlock spin;const char *deviceName;const char *clockName;uint32_t deviceIndex;const struct ClockLockMethod *lockOps;void *clk;void *priv;struct ClockDevice *parent; };
- ClockDevice成员钩子函数结构体ClockMethod的实例化。
ClockLockMethod钩子函数结构体本例未实现,若要实例化,可参考I2C驱动开发。
struct ClockMethod {int32_t (*start)(struct ClockDevice *device);int32_t (*stop)(struct ClockDevice *device);int32_t (*setRate)(struct ClockDevice *device, uint32_t rate);int32_t (*getRate)(struct ClockDevice *device, uint32_t *rate);int32_t (*disable)(struct ClockDevice *device);int32_t (*enable)(struct ClockDevice *device);struct ClockDevice *(*getParent)(struct ClockDevice *device);int32_t (*setParent)(struct ClockDevice *device, struct ClockDevice *parent); };
-
Init函数开发参考
入参:
HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。
返回值:
HDF_STATUS相关状态(表4为部分展示,如需使用其他状态,可参考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h中HDF_STATUS定义)。
表 4 HDF_STATUS相关状态说明
状态(值) 问题描述 HDF_ERR_INVALID_OBJECT 控制器对象非法 HDF_ERR_INVALID_PARAM 参数非法 HDF_ERR_MALLOC_FAIL 内存分配失败 HDF_ERR_IO I/O错误 HDF_SUCCESS 传输成功 HDF_FAILURE 传输失败 函数说明:
初始化自定义结构体对象,初始化ClockDevice成员,并调用核心层ClockDeviceAdd函数。
static int32_t LinuxClockInit(struct HdfDeviceObject *device) {int32_t ret = HDF_SUCCESS;struct DeviceResourceNode *childNode = NULL;if (device == NULL || device->property == NULL) {HDF_LOGE("LinuxClockInit: device or property is null");return HDF_ERR_INVALID_OBJECT;}DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {ret = ClockParseAndDeviceAdd(device, childNode);if (ret != HDF_SUCCESS) {HDF_LOGE("LinuxClockInit: clock init fail!");return ret;}}HDF_LOGE("LinuxClockInit: clock init success!");return HDF_SUCCESS; }static int32_t ClockParseAndDeviceAdd(struct HdfDeviceObject *device, struct DeviceResourceNode *node) {int32_t ret;struct ClockDevice *clockDevice = NULL;(void)device;clockDevice = (struct ClockDevice *)OsalMemCalloc(sizeof(*clockDevice));if (clockDevice == NULL) {HDF_LOGE("ClockParseAndDeviceAdd: alloc clockDevice fail!");return HDF_ERR_MALLOC_FAIL;}ret = ClockReadDrs(clockDevice, node);if (ret != HDF_SUCCESS) {HDF_LOGE("ClockParseAndDeviceAdd: read drs fail, ret: %d!", ret);OsalMemFree(clockDevice);return ret;}clockDevice->priv = (void *)node;clockDevice->ops = &g_method;ret = ClockDeviceAdd(clockDevice);if (ret != HDF_SUCCESS) {HDF_LOGE("ClockParseAndDeviceAdd: add clock device:%u fail!", clockDevice->deviceIndex);OsalMemFree(clockDevice);return ret;}return HDF_SUCCESS; }static int32_t ClockReadDrs(struct ClockDevice *clockDevice, const struct DeviceResourceNode *node) {int32_t ret;struct DeviceResourceIface *drsOps = NULL;drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {HDF_LOGE("ClockReadDrs: invalid drs ops!");return HDF_ERR_NOT_SUPPORT;}ret = drsOps->GetUint32(node, "deviceIndex", &clockDevice->deviceIndex, 0);if (ret != HDF_SUCCESS) {HDF_LOGE("ClockReadDrs: read deviceIndex fail, ret: %d!", ret);return ret;}drsOps->GetString(node, "clockName", &clockDevice->clockName, 0);ret = drsOps->GetString(node, "deviceName", &clockDevice->deviceName, 0);if (ret != HDF_SUCCESS) {HDF_LOGE("ClockReadDrs: read deviceName fail, ret: %d!", ret);return ret;}return HDF_SUCCESS; }
-
Release函数开发参考
入参:
HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。
返回值:
无。
函数说明: 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。
static void LinuxClockRelease(struct HdfDeviceObject *device) {const struct DeviceResourceNode *childNode = NULL;if (device == NULL || device->property == NULL) {HDF_LOGE("LinuxClockRelease: device or property is null!");return;}DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {ClockRemoveByNode(childNode);} }static void ClockRemoveByNode(const struct DeviceResourceNode *node) {int32_t ret;int32_t deviceIndex;struct ClockDevice *device = NULL;struct DeviceResourceIface *drsOps = NULL;drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);if (drsOps == NULL || drsOps->GetUint32 == NULL) {HDF_LOGE("ClockRemoveByNode: invalid drs ops!");return;}ret = drsOps->GetUint32(node, "deviceIndex", (uint32_t *)&deviceIndex, 0);if (ret != HDF_SUCCESS) {HDF_LOGE("ClockRemoveByNode: read deviceIndex fail, ret: %d!", ret);return;}device = ClockDeviceGet(deviceIndex);if (device != NULL && device->priv == node) {ret = ClockStop(device);if (ret != HDF_SUCCESS) {HDF_LOGE("ClockRemoveByNode: close fail, ret: %d!", ret);}if (device->parent && device->parent->deviceName == NULL) {ClockDeviceRemove(device->parent);OsalMemFree(device->parent);}ClockDeviceRemove(device);OsalMemFree(device);} }
-
-
驱动调试
【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的测试用例是否成功等。
相关文章:
OpenHarmony平台驱动开发(二),CLOCK
OpenHarmony平台驱动开发(二) CLOCK 概述 功能简介 CLOCK,时钟是系统各个部件运行的基础,以CPU时钟举例,CPU 时钟是指 CPU 内部的时钟发生器,它以频率的形式工作,用来同步和控制 CPU 内部的各…...
Java大厂面试:Java技术栈中的核心知识点
Java技术栈中的核心知识点 第一轮提问:基础概念与原理 技术总监:郑薪苦,你对JVM内存模型了解多少?能简单说说吗?郑薪苦:嗯……我记得JVM有堆、栈、方法区这些区域,堆是存放对象的地方…...
硬件加速模式Chrome(Edge)闪屏
Chrome开启“硬件加速模式”后,打开浏览器会闪屏或看视频会闪屏,如果电脑只有集显,直接将这个硬件加速关了吧,没啥必要开着 解决方法 让浏览器使用独立显卡 在Windows左下角搜索 图形设置 ,将浏览器添加进去&#…...
【ArcGIS微课1000例】0145:如何按照自定义形状裁剪数据框?
文章目录 一、添加数据二、绘制形状三、裁剪格网和经纬网一、添加数据 打开软件,添加配套实验数据包中0145.rar中的影像数据,如下图所示: 二、绘制形状 1. 在数据视图中,使用绘图 工具条上的新建圆工具 可创建一个椭圆,使其包含要在该数据框中显示的数据范围。 修改椭圆…...
深入了解Linux系统—— 环境变量
命令行参数 我们知道,我们使用的指令它本质上也是一个程序,我们要执行这个指令,输入指令名然后回车即可执行;但是对于指令带选项,又是如何实现的呢? 问题:main函数有没有参数? 在我…...
软考-软件设计师中级备考 12、软件工程
一、软件工程概述 定义:软件工程是一门研究用工程化方法构建和维护有效的、实用的和高质量软件的学科。它涉及到软件的开发、测试、维护、管理等多个方面,旨在运用一系列科学方法和技术手段,提高软件的质量和开发效率,降低软件开…...
FreeSwitch Windows安装
下载 FreeSwitch 官网下载地址https://files.freeswitch.org/windows/ 根据自己的系统选择不同的版本,如下图 官网下载可能比较慢,请使用下方下载 FreeSWITCH-1.10.12-Release-x64.msi https://download.csdn.net/download/a670941001/90752912 2、…...
南京优质的公司有哪些?
南京有许多优质的公司,以下是一些有代表性的: 制造业 • 南京钢铁集团有限公司 :作为国家战略布局的 18 家重点钢企之一,是中国特大型钢铁联合企业,1993 年 12 月进行公司制改革,2010 年 9 月实现整体上市…...
Spring AI 实战:第十一章、Spring AI Agent之知行合一
引言:智能体的知行辩证法 “知为行之始,行为知之成”,王阳明的哲学智慧在AI时代焕发光彩。智能体(LLM Agent)的进化之路,正是"认知-决策-执行"这一闭环的完美诠释: 知明理:融合大语言模型的推理能力与知识图谱的结构化认知行致用:基于ReAct模式的动态工具调…...
LeetCode 1128 等价多米诺骨牌对的数量 题解
今天的每日一题,我的思路还是硬做,不如评论区通过状压写的简单,但是答题思路加算法实现是没有问题的,且时间复杂度也是可以通过的,毕竟全是o(n) 那么我就来说一下我的思路,根据dominoes[i] [a, b] 与 domi…...
管理配置信息和敏感信息
管理配置信息和敏感信息 文章目录 管理配置信息和敏感信息[toc]一、什么是ConfigMap和Secret二、使用ConfigMap为Tomcat提供配置文件三、使用Secret为MongDB提供配置文件 一、什么是ConfigMap和Secret 在 Kubernetes 中,ConfigMap 和 Secret 是两种用于管理配置数据…...
Rust与C/C++互操作实战指南
目录 1.前言2.动态库调用2.1 动态加载2.2 静态加载3.代码调用4.静态库调用1.前言 本文原文为:Rust与C/C++互操作实战指南 由于rust诞生时间太短,目前生态不够完善,因此大量的功能库都需要依赖于C、C++语言的历史积累。 而本文将要介绍的便是如何实现rust与c乃至c++之间实…...
word批量转pdf工具
word批量转pdf工具 图片 说到了办公,怎能不提PDF转换哦? 这是一款一键就可以批量word转换为PDF的小工具,简直是VB界的一股清流。 图片 操作简单到不行,只要把需要转换的word文件和这个工具放在同一个文件夹里,双击…...
【数据结构】励志大厂版·初阶(复习+刷题)排序
前引:本篇作为初阶结尾的最后一篇—排序,将先介绍八种常用的排序方法,然后开始刷题,小编会详细注释每句代码的作用,不会出现看不懂的情况,这点大家放心,既是写给大家同时也是写给自己的…...
Git推送大文件导致提交回退的完整解决记录
问题背景 在向Gitee推送代码时,因单文件超过平台限制(100MB),推送被拒绝: > git push origin master:master remote: File [6322bc3f1becedcade87b5d1ea7fddbdd95e6959] size 178.312MB, exceeds quota 100MB rem…...
游戏引擎学习第257天:处理一些 Win32 相关的问题
设定今天的工作计划 今天我们本来是打算继续开发性能分析器(Profiler),但在此之前,我们认为有一些问题应该先清理一下。虽然这类事情不是我们最关心的核心内容,但我们觉得现在是时候处理一下了,特别是为了…...
高性能数据库架构探索:OceanBase 分布式技术深入解析
高性能数据库架构探索:OceanBase 分布式技术深入解析 简介 OceanBase 高性能分布式数据库,解决传统数据库在大规模、高并发场景下的性能瓶颈,通过分布式架构、数据自动分片和强一致性协议,提供高可用性、弹性扩展和出色的性能&am…...
【CISCO】Se2/0, Se3/0:串行口(Serial) 这里串口的2/0 和 3/0分别都是什么?
在 Cisco IOS 设备上,接口名称通常遵循这样一个格式: <类型><槽号>/<端口号>类型(Type):表示接口的物理或逻辑类型,比如 Serial(串行)、FastEthernet、GigabitEt…...
GPU集群训练经验评估框架:运营经理经验分析篇
引言 随着深度学习模型规模的持续增长和复杂度的不断提高,单GPU训练已经难以满足现代AI研究和应用的需求。GPU集群训练作为一种有效的扩展方案,能够显著提升训练效率、处理更大规模的数据集和模型。然而,GPU集群训练涉及到分布式训练框架、集群管理工具、性能优化等多个技术…...
函数多项式拟合
函数多项式拟合 用处 不方便使用math时,可以使用多项式拟合法实现比较高效的数学函数,比如使用avx指令时,O3优化,math中的函数会调用FPU指令集,在指令集切换的过程中代码效率大幅降低,为避免使用math中的…...
【Hive入门】Hive与Spark SQL集成:混合计算实践指南
目录 引言 1 Hive与Spark SQL概述 1.1 Hive简介 1.2 Spark SQL简介 2 Hive与Spark SQL集成架构 2.1 集成原理 2.2 配置集成环境 3 混合计算使用场景 3.1 场景一:Hive表与Spark DataFrame互操作 3.2 场景二:Hive UDF与Spark SQL结合使用 3.3 场…...
TFQMR和BiCGStab方法比较
TFQMR(Transpose-Free Quasi-Minimal Residual)和BiCGStab(Bi-Conjugate Gradient Stabilized)都是用于求解非对称线性方程组的迭代方法,属于Krylov子空间方法的范畴。它们分别是BiCG(双共轭梯度法…...
小程序 IView WeappUI组件库(简单增删改查)
IView Weapp 微信小程序UI组件库:https://weapp.iviewui.com/components/card IView Weapp.png 快速上手搭建 快速上手.png iView Weapp 的代码 将源代码下载下来,然后将dict放到自己的项目中去。 iView Weapp 的代码.png 小程序中添加iView Weapp 将di…...
nginx 核心功能 02
目录 1. 正向代理 1.1 编译安装 Nginx 1.2 配置正向代理 2. 反向代理 2.1 配置nginx七层代理 2.2 配置nginx四层代理 3. Nginx 缓存 3.1 缓存功能的核心原理和缓存类型 3.2 代理缓存功能设置 4. Nginx rewrite 和正则 4.1 Nginx正则 4.2 nginx location 4.3 Rewri…...
LeetCode 102题解 | 二叉树的层序遍历
二叉树的层序遍历 一、题目链接二、题目三、算法原理四、编写代码 一、题目链接 二叉树的层序遍历 二、题目 三、算法原理 本题要求把结果放在不规则的二维数组里,即每一层二叉树的数值放在一行数组中。 回顾之前的层序遍历是借助队列实现的,是不考虑…...
Flink基础整理
文章目录 前言1.Flink系统架构2.编程模型(API层次结构)3.DataSet和DataStream区别4.Flink的批流统一5.Flink的状态后端6.Flink有哪些状态类型7.Flink并行度前言 提示:下面是根据网络或AI整理: 1.Flink系统架构 用户在客户端提交作业(Job)到服务端。服务端为分布式的主从…...
C++23 新特性:为 std::pair 的转发构造函数添加默认实参
文章目录 1\. 背景:std::pair 的转发构造函数2\. C23 的改进:添加默认实参示例代码 3\. 带来的好处3.1 更简洁的代码3.2 提高代码的可维护性3.3 与 std::optional 和 std::variant 的协同 4\. 实现细节示例实现(简化版) 5\. 使用场…...
JavaScript性能优化实战(9):图像与媒体资源优化
引言 在当今视觉驱动的网络环境中,图像和媒体资源往往占据了网页总下载量的60%-80%,因此对图像和媒体资源进行有效优化已成为前端性能提升的关键领域。尽管网络带宽持续提升,但用户对加载速度的期望也在不断提高,特别是在移动设备和网络条件不稳定的场景下。 本文作为Jav…...
施磊老师rpc(四)
文章目录 rpc网络服务简介RpcProvider 的设计目标Eventloop不使用智能指针-弃用RpcProvider类似于集群的服务器provider网络实现**src/include/rpcprovider.h****src/include/mprpcapplication.h****src/rpcprovider.cc** 错误1错误2-重点**本项目的 mprpc 是动态库, muduo..是…...
Java学习手册:MyBatis 框架作用详解
一、MyBatis 简介 MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发。它通过将 Java 对象与数据库表之间的映射关系进行配置,使得开发者可以使用简单的 SQL 语句和 Java 代码来完成复杂的数据操作。MyBatis 支持自定义 SQL 语句,提供了灵…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】3.1 数据质量评估指标(完整性/一致性/准确性)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 数据质量评估核心指标:完整性、一致性、准确性实战解析3.1 数据质量评估指标体系3.1.1 完整性:数据是否存在缺失1.1.1 核心定义与业务影响1.1.2 检测…...
分布式系统中的 ActiveMQ:异步解耦与流量削峰(一)
一、引言 在当今数字化时代,分布式系统已成为构建大规模应用的关键架构。随着业务的快速发展和用户量的急剧增长,分布式系统面临着诸多挑战,其中异步通信、系统解耦和流量削峰是亟待解决的重要问题。 以电商系统为例,在秒杀活动中…...
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】2.5 事务与锁机制(ACID特性/事务控制语句)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 PostgreSQL 事务与锁机制深度解析:ACID 特性与事务控制全流程2.5 事务与锁机制2.5.1 ACID 特性与实现原理2.5.1.1 ACID 核心概念2.5.1.2 MVCC(多版本并发控制)与WAL(预写式日志)协同效应2.5.2 事务…...
STM32教程:ADC原理及程序(基于STM32F103C8T6最小系统板标准库开发)*详细教程*
前言: 本文章介绍了STM32微控制器的ADC外设,介绍了ADC的底层原理以及基本结构,介绍了ADC有关的标准库函数,以及如何编写代码实现ADC对电位器电压的读取。 可以根据基本结构图来编写代码 大体流程: 1、开启RCC时钟&am…...
RabbitMQ 深度解析:从核心组件到复杂应用场景
一.RabbitMQ简单介绍 消息队列作为分布式系统中不可或缺的组件,承担着解耦系统组件、保障数据可靠传输、提高系统吞吐量等重要职责。在众多消息队列产品中,RabbitMQ 凭借其可靠性和丰富的特性,在企业级应用中获得了广泛应用。本研究报告将全…...
linux 使用nginx部署ssl证书,将http升级为https
前言 本文基于:操作系统 CentOS Stream 8 使用工具:Xshell8、Xftp8 服务器基础环境: nginx - 请查看 linux 使用nginx部署vue、react项目 所需服务器基础环境,请根据提示进行下载、安装。 1.下载证书 以腾讯云为例ÿ…...
iview 分页改变每页条数时请求两次问题
问题 在iview page分页的时候,修改每页条数时,会发出两次请求。 iview 版本是4.0.0 原因 iview 的分页在调用on-page-size-change之前会调用on-Change。默认会先调用on-Change回到第一页,再调用on-page-size-change改变分页显示数量 此时就会…...
【Hive入门】Hive与Spark SQL深度集成:Metastore与Catalog兼容性全景解析
目录 引言 1 元数据管理体系架构对比 1.1 Hive Metastore架构解析 1.2 Spark Catalog系统设计 2 元数据兼容性深度剖析 2.1 元数据模型映射关系 2.2 元数据同步机制 3 生产环境配置指南 3.1 基础兼容性配置 3.1.1 Spark连接Hive Metastore 3.1.2 多引擎共享配置 3.…...
C#与西门子PLC通信:S7NetPlus和HslCommunication使用指南
西门子S7协议是用来和PLC进行通讯的一个协议,默认端口是102,数据会保存在一个个DB块中,比较经典的用法是一个DB块专门用来读取,一个用来写入。 DB(数据块) {块号}.DBX/DBD/DBW{字节地址}.{位偏移} 1、数据…...
湖北理元理律师事务所:法律科技融合下的债务管理实践
随着债务纠纷数量攀升,如何通过合法途径化解债务风险成为社会焦点。湖北理元理律师事务所作为国家司法局注册的债事服务机构,尝试以“法律技术”重构传统服务模式,为债务人提供系统性解决方案。 专业化服务架构 该律所设立客服、运营、法务…...
Spring Cloud Gateway MVC 基于 Spring Boot 3.4 以 WAR 包形式部署于外部 Tomcat 实战
一、引言 随着微服务架构的广泛应用,Spring Cloud Gateway 作为网关层的核心组件,为服务间的通信与流量管理提供了强大支持。spring-cloud-starter-gateway-mvc 则进一步助力开发者以熟悉的 MVC 模式进行网关开发。同时,将项目以 WAR 包形式…...
LLM论文笔记 27: Looped Transformers for Length Generalization
Arxiv日期:2024.9.25 关键词 长度泛化 transformer结构优化 核心结论 1. RASP-L限制transformer无法处理包含循环的任务的长度泛化 2. Loop Transformer显著提升了长度泛化能力 Input Injection 显著提升了模型的长度泛化性能,尤其在二进制加法等复杂…...
PCIe TLP | 报头 / 包格式 / 地址转换 / 寄存器 / 配置空间类型
注:本文为 “PCIe TLP” 相关文章合辑。 英文引文,机翻未校。 中文引文,未整理去重。 图片清晰度受引文原图所限。 略作重排,如有内容异常,请看原文。 PCIe - TLP Header, Packet Formats, Address Translation, Conf…...
《AI大模型应知应会100篇》第46篇:大模型推理优化技术:量化、剪枝与蒸馏
第46篇:大模型推理优化技术:量化、剪枝与蒸馏 📌 目标读者:人工智能初中级入门者 🧠 核心内容:量化、剪枝、蒸馏三大核心技术详解 实战代码演示 案例部署全流程 💻 实战平台:PyTor…...
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 20)
🎁个人主页:工藤新一 🔍系列专栏:C面向对象(类和对象篇) 🌟心中的天空之城,终会照亮我前方的路 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录 三…...
【Python生成器与迭代器】核心原理与实战应用
目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比二、实战演示环境配置要求核心代码实现案例1:自定义迭代器类案例2:生成器函数案例3:生成器表达式运行结果验证三、性能对比测试方法论量…...
2025年最新嵌入式开发STM32单片机详细教程(更新中)
ARM 处理器架构 ARM 处理器从 1984 ARM-1 发展到 2004 ARM-11 之后,放弃数字命名,用 cortex 来命令处理器产品。 Cortex-A系列 主打高性能 手机,平板,智能电视等 Cortex-R系列 主打实时 汽车,工业控…...
neatchat轻量级丝滑的ai模型web客户端
NeatChat 人工智能模型对话web客户端 前言 此项目是nextchat分支,相比原者更加简洁流畅。 部署 docker部署 name: next-chat services:chatgpt-next-web:ports:- 8080:3000environment:- OPENAI_API_KEYsk-xx543Ef3d- BASE_URLhttps://api.ai.com- GOOGLE_API_K…...
学习黑客分析案例
▶️ Day 2 任务 – 「怪物图鉴」实战 选一条最新安全事件(国内外均可,建议 1 年内) 例:CVE-2024-21887 Ivanti VPN RCE 用下列表格框架,3 句话归纳它的“派系”“CIA 受击点”“一句话原理”: 攻击流派…...
sonar-scanner在扫描JAVA项目时为什么需要感知.class文件
1 概述 SonarQube是一个静态代码分析工具,主要用于检查源代码的质量,包括代码重复、潜在漏洞、代码风格问题等。而SonarScanner是SonarQube的客户端工具,负责将代码进行形态分析,并将结果发送到SonarQube服务器。所以,…...