Harmony鸿蒙南向驱动开发-SDIO

news2025/9/21 16:35:47

SDIO(Secure Digital Input and Output)由SD卡发展而来,与SD卡统称为MMC(MultiMediaCard),二者使用相同的通信协议。SDIO接口兼容以前的SD卡,并且可以连接支持SDIO接口的其他设备。

运作机制

在HDF框架中,SDIO的接口适配模式采用独立服务模式(如图1)。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,若设备过多可能增加内存占用。

独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为:

  • 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。

  • device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。

SDIO模块各分层作用:

  • 接口层提供打开SDIO设备、设置块的大小、读取数据、写数据、设置公共信息、获取公共信息、刷新数据、独占HOST、释放Host、使能SDIO功能设备、去使能SDIO功能设备、申请中断、释放中断关闭SDIO设备的接口。

  • 核心层主要提供SDIO控制器的添加、移除及管理的能力,通过钩子函数与适配层交互。

  • 适配层主要是将钩子函数的功能实例化,实现具体的功能。

图 1 SDIO独立服务模式结构图

SDIO独立服务模式结构图

约束与限制

SDIO模块API当前仅支持内核态调用。

开发指导

场景介绍

SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。当驱动开发者需要将SDIO设备适配到OpenHarmony时,需要进行SDIO驱动适配,下文将介绍如何进行SDIO驱动适配。

接口说明

为了保证上层在调用SDIO接口时能够正确的操作硬件,核心层在//drivers/hdf_core/framework/model/storage/include/mmc/mmc_sdio.h中定义了以下钩子函数。驱动适配者需要在适配层实现这些函数的具体功能,并与这些钩子函数挂接,从而完成接口层与核心层的交互。

SdioDeviceOps定义:

struct SdioDeviceOps {
    int32_t (*incrAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
    int32_t (*incrAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
    int32_t (*fixedAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
    int32_t (*fixedAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
    int32_t (*func0ReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
    int32_t (*func0WriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
    int32_t (*setBlockSize)(struct SdioDevice *dev, uint32_t blockSize);
    int32_t (*getCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);
    int32_t (*setCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);
    int32_t (*flushData)(struct SdioDevice *dev);
    int32_t (*enableFunc)(struct SdioDevice *dev);
    int32_t (*disableFunc)(struct SdioDevice *dev);
    int32_t (*claimIrq)(struct SdioDevice *dev, SdioIrqHandler *irqHandler);
    int32_t (*releaseIrq)(struct SdioDevice *dev);
    int32_t (*findFunc)(struct SdioDevice *dev, struct SdioFunctionConfig *configData);
    int32_t (*claimHost)(struct SdioDevice *dev);
    int32_t (*releaseHost)(struct SdioDevice *dev);
};

表 1 SdioDeviceOps结构体成员的钩子函数功能说明

函数入参出参返回值功能
incrAddrReadBytesdev:结构体指针,SDIO设备控制器
addr:uint32_t类型,地址值
size:uint32_t类型,大小
data:uint8_t类型指针,传出值HDF_STATUS相关状态从指定的SDIO地址增量读取给定长度的数据
incrAddrWriteBytesdev:结构体指针,SDIO设备控制器
data:uint8_t类型指针,传入值
addr:uint32_t类型,地址值
size:uint32_t类型,大小
HDF_STATUS相关状态将给定长度的数据增量写入指定的SDIO地址
fixedAddrReadBytesdev:结构体指针,SDIO设备控制器
addr:uint32_t类型,地址值
size:uint32_t类型,大小
scatterLen:uint32_t类型,数据长度
data:uint8_t类型指针,传出值HDF_STATUS相关状态从固定SDIO地址读取给定长度的数据。
fixedAddrWriteBytesdev:结构体指针,SDIO设备控制器
data:uint8_t类型指针,传入值
addr:uint32_t类型,地址值
size:uint32_t类型,大小
scatterLen:uint32_t类型,数据长度
HDF_STATUS相关状态将给定长度的数据写入固定SDIO地址
func0ReadBytesdev:结构体指针,SDIO设备控制器
addr:uint32_t类型,地址值
size:uint32_t类型,大小
data:uint8_t类型指针,传出值HDF_STATUS相关状态从SDIO函数0的地址空间读取给定长度的数据。
func0WriteBytesdev:结构体指针,SDIO设备控制器
data:uint8_t类型指针,传入值
addr:uint32_t类型,地址值
size:uint32_t类型,大小
HDF_STATUS相关状态将给定长度的数据写入SDIO函数0的地址空间。
setBlockSizedev:结构体指针,SDIO设备控制器
blockSize:uint32_t类型,Block大小
HDF_STATUS相关状态设置block大小
getCommonInfodev:联合体指针,SDIO设备控制器
infoType:uint32_t类型,info类型
info:结构体指针,传出SdioFuncInfo信息HDF_STATUS相关状态获取CommonInfo,说明见下
setCommonInfodev:结构体指针,SDIO设备控制器
info:联合体指针,SdioFuncInfo信息传入
infoType:uint32_t类型,info类型
HDF_STATUS相关状态设置CommonInfo,说明见下
flushDatadev:结构体指针,SDIO设备控制器HDF_STATUS相关状态当SDIO需要重新初始化或发生意外错误时调用的函数
enableFuncdev:结构体指针,SDIO设备控制器HDF_STATUS相关状态使能SDIO设备
disableFuncdev:结构体指针,SDIO设备控制器HDF_STATUS相关状态去使能SDIO设备
claimIrqdev:结构体指针,SDIO设备控制器
irqHandler:void函数指针
HDF_STATUS相关状态注册SDIO中断
releaseIrqdev:结构体指针,SDIO设备控制器HDF_STATUS相关状态释放SDIO中断
findFuncdev:结构体指针,SDIO设备控制器
configData:结构体指针,SDIO函数关键信息
HDF_STATUS相关状态寻找匹配的funcNum
claimHostdev:结构体指针,SDIO设备控制器HDF_STATUS相关状态独占HOST
releaseHostdev:结构体指针,SDIO设备控制器HDF_STATUS相关状态释放HOST

说明:
CommonInfo包括maxBlockNum(单个request中最大block数)、maxBlockSize(单个block最大字节数)、maxRequestSize(单个Request最大字节数)、enTimeout(最大超时时间,毫秒)、funcNum(功能编号1~7)、irqCap(IRQ capabilities)、(void *)data。

开发步骤

SDIO模块适配包含以下四个步骤:

  1. 实例化驱动入口

    • 实例化HdfDriverEntry结构体成员。

    • 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。

  2. 配置属性文件

    • 在device_info.hcs文件中添加deviceNode描述。

    • 【可选】添加sdio_config.hcs器件属性文件。

  3. 实例化SDIO控制器对象

    • 初始化SdioDevice成员。

    • 实例化SdioDevice成员SdioDeviceOps。

      说明:
      实例化SdioDevice成员SdioDeviceOps,其定义和成员说明见接口说明。

  4. 驱动调试

    【可选】针对新增驱动程序,建议验证驱动基本功能,例如SDIO控制状态,中断响应情况,读写数据是否成功等。

开发实例

下方将以//drivers/hdf_core/adapter/khdf/linux/model/storage/sdio_adapter.c为示例,展示需要驱动适配者提供哪些内容来完整实现设备功能。

  1. 实例化驱动入口

    驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。

    一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。

    SDIO 驱动入口参考:

    struct HdfDriverEntry g_sdioDriverEntry = {
        .moduleVersion = 1,
        .Bind = Hi35xxLinuxSdioBind,         // 见Bind开发参考
        .Init = Hi35xxLinuxSdioInit,         // 见Init开发参考
        .Release = Hi35xxLinuxSdioRelease,   // 见Release开发参考
        .moduleName = "HDF_PLATFORM_SDIO",   // 【必要且与HCS文件中里面的moduleName匹配】
    };
    HDF_INIT(g_sdioDriverEntry);             // 调用HDF_INIT将驱动入口注册到HDF框架中
  2. 配置属性文件

    完成驱动入口注册之后,下一步请在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode信息,并在sdio_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值与核心层SdioDevice成员的默认值或限制范围有密切关系。本例只有一个SDIO控制器,如有多个器件信息,则需要在device_info.hcs文件增加deviceNode信息,以及在sdio_config文件中增加对应的器件属性。

    独立服务模式的特点是device_info.hcs文件中设备节点代表着一个设备对象,如果存在多个设备对象,则按需添加,注意服务名与驱动私有数据匹配的关键字名称必须唯一。其中各项参数如表2所示:

    表 2 device_info.hcs节点参数说明

    成员名
    policy驱动服务发布的策略,SDIO设备控制器具体配置为1,表示驱动对内核态发布服务
    priority驱动启动优先级(0-200),值越大优先级越低。SDIO设备控制器具体配置为30
    permission驱动创建设备节点权限,SDIO设备控制器具体配置为0664
    moduleName驱动名称,SDIO设备控制器固定为hi3516_mmc_driver
    serviceName驱动对外发布服务的名称,SDIO设备控制器服务名设置为HDF_PLATFORM_MMC_2
    deviceMatchAttr驱动私有数据匹配的关键字,SDIO设备控制器设置为hi3516_mmc_sdio
    • device_info.hcs 配置参考:

      root {
          device_info {
              match_attr = "hdf_manager";
              platform :: host {
                  hostName = "platform_host";
                  priority = 50;
                  device_sdio :: device {
                      device0 :: deviceNode {
                          policy = 1;
                          priority = 70;
                          permission = 0644;
                          moduleName = "HDF_PLATFORM_SDIO";            // 【必要】用于指定驱动名称,需要与驱动Entry中的moduleName一致。
                          serviceName = "HDF_PLATFORM_MMC_2";          // 【必要】驱动对外发布服务的名称,必须唯一。
                          deviceMatchAttr = "hisilicon_hi35xx_sdio_0"; // 【必要】用于配置控制器私有数据,要与sdio_config.hcs中对应控制器保持一致。
                      }
                  }
              }
          }
      }
    • sdio_config.hcs 配置参考:

      root {
          platform {
              sdio_config {
                  template sdio_controller {
                      match_attr = "";
                      hostId = 2;                             // 【必要】模式固定为2,在mmc_config.hcs有介绍。
                      devType = 2;                            // 【必要】模式固定为2,在mmc_config.hcs有介绍。
                  }
                  controller_0x2dd1 :: sdio_controller {
                      match_attr = "hisilicon_hi35xx_sdio_0"; // 【必要】需要和device_info.hcs中的deviceMatchAttr值一致。
              }
          }
      }

      需要注意的是,新增sdio_config.hcs配置文件后,必须在hdf.hcs文件中包含sdio_config.hcs所在路径信息,否则配置文件无法生效。

  3. 实例化SDIO设备控制器对象

    完成属性文件配置之后,下一步就是以核心层SdioDevice对象的初始化为核心,包括驱动适配者自定义结构体(传递参数和数据),实例化SdioDevice成员SdioDeviceOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind、Init、Release)。

    • 自定义结构体参考:

      从驱动的角度看,自定义结构体是参数和数据的载体,而且sdio_config.hcs文件中的数值会被HDF读入并通过DeviceResourceIface来初始化结构体成员,一些重要数值也会传递给核心层对象。

      typedef struct {
          uint32_t maxBlockNum;    // 单个request最大的block个数
          uint32_t maxBlockSize;   // 单个block最大的字节数1~2048
          uint32_t maxRequestSize; // 单个request最大的字节数1~2048
          uint32_t enTimeout;      // 最大超时时间,单位毫秒,且不能超过一秒。
          uint32_t funcNum;        // 函数编号1~7
          uint32_t irqCap;         // 中断能力
          void *data;              // 私有数据
      } SdioFuncInfo;
      
      // SdioDevice是核心层控制器结构体,其中的成员在Bind函数中会被赋值。
      struct SdioDevice {
          struct SdDevice sd;
          struct SdioDeviceOps *sdioOps;
          struct SdioRegister sdioReg;
          uint32_t functions;
          struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER];
          struct SdioFunction *curFunction;
          struct OsalThread thread; // 中断线程
          struct OsalSem sem;
          bool irqPending;
          bool threadRunning;
      };
    • SdioDevice成员钩子函数结构体SdioDeviceOps的实例化。

      static struct SdioDeviceOps g_sdioDeviceOps = {
          .incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes,
          .incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes,
          .fixedAddrReadBytes = Hi35xxLinuxSdioFixedAddrReadBytes,
          .fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes,
          .func0ReadBytes = Hi35xxLinuxSdioFunc0ReadBytes,
          .func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes,
          .setBlockSize = Hi35xxLinuxSdioSetBlockSize,
          .getCommonInfo = Hi35xxLinuxSdioGetCommonInfo,
          .setCommonInfo = Hi35xxLinuxSdioSetCommonInfo,
          .flushData = Hi35xxLinuxSdioFlushData,
          .enableFunc = Hi35xxLinuxSdioEnableFunc,
          .disableFunc = Hi35xxLinuxSdioDisableFunc,
          .claimIrq = Hi35xxLinuxSdioClaimIrq,
          .releaseIrq = Hi35xxLinuxSdioReleaseIrq,
          .findFunc = Hi35xxLinuxSdioFindFunc,
          .claimHost = Hi35xxLinuxSdioClaimHost,
          .releaseHost = Hi35xxLinuxSdioReleaseHost,
      };
    • Bind函数开发参考

      入参:

      HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。

      返回值:

      HDF_STATUS相关状态 (表3为部分展示,如需使用其他状态,可参考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h中HDF_STATUS的定义)。

      表 3 HDF_STATUS相关状态说明

      状态(值)问题描述
      HDF_ERR_INVALID_OBJECT控制器对象非法
      HDF_ERR_MALLOC_FAIL内存分配失败
      HDF_ERR_IOI/O 错误
      HDF_SUCCESS初始化成功
      HDF_FAILURE初始化失败

      函数说明:

      初始化自定义结构体对象,初始化SdioCntlr成员,调用核心层SdioCntlrAdd函数,以及其他驱动适配者自定义初始化操作。

      static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
      {
          struct MmcCntlr *cntlr = NULL;
          int32_t ret;
          ......
          cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// 分配内存
          ......
          cntlr->ops = &g_sdioCntlrOps;                                     // 【必要】struct MmcCntlrOps g_sdioCntlrOps={
                                                                            // .rescanSdioDev = Hi35xxLinuxSdioRescan,};
          cntlr->hdfDevObj = obj;                                           // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
          obj->service = &cntlr->service;                                   // 【必要】使HdfDeviceObject与MmcCntlr可以相互转化的前提
          ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);                      // 【必要】初始化cntlr的index、devType,失败则goto _ERR。
          ......
          ret = MmcCntlrAdd(cntlr);                                         // 【必要】调用核心层mmc_core.c的函数,失败则goto _ERR。
          ......
          ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);   // 【必要】调用核心层mmc_core.c的函数,失败则goto _ERR。
          ......
      
          MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);                 // 【必要】调用核心层mmc_core.c的函数,钩子函数挂载。
          HDF_LOGD("Hi35xxLinuxSdioBind: Success!");
          return HDF_SUCCESS;
      
      _ERR:
          Hi35xxLinuxSdioDeleteCntlr(cntlr);
          HDF_LOGE("Hi35xxLinuxSdioBind: Fail!");
          return HDF_FAILURE;
      }
    • Init函数开发参考

      入参:

      HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。

      返回值:

      HDF_STATUS相关状态。

      函数说明:

      无操作,可根据驱动适配者需要添加。

      static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
      {
          (void)obj;        // 无操作,可根据驱动适配者的需要进行添加
          HDF_LOGD("Hi35xxLinuxSdioInit: Success!");
          return HDF_SUCCESS;
      }
    • Release函数开发参考

      入参:

      HdfDeviceObject是整个驱动对外提供的接口参数,具备HCS配置文件的信息。

      返回值:

      无。

      函数说明:

      释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。

      说明:
      所有强制转换获取相应对象的操作前提是在Bind函数中具备对应赋值的操作。

      static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj)
      {
          if (obj == NULL) {
              return;
          }
          Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service); // 【必要】自定义的内存释放函数,这里有HdfDeviceObject到MmcCntlr的强制转换
      }
  4. 驱动调试

    【可选】针对新增驱动程序,建议验证驱动基本功能,例如SDIO控制状态,中断响应情况,读写数据是否成功等。

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

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

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

相关文章

Java项目:基于Springboot+vue实现的中国陕西民俗前后台管理系统设计与实现(源码+数据库+毕业论文)

一、项目简介 本项目是一套基于Springbootvue实现的中国陕西民俗管理系统设计与实现设 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界…

Python学习之-pyechart详解

前言: 什么是pyechart? Pyecharts 是一个用于生成 Echarts 图表的 Python 库。Echarts 是一个由百度开源的数据可视化工具,它提供的图表种类丰富,交互性强,兼容性好,非常适合用于数据分析结果的展示。Pyec…

Golang | Leetcode Golang题解之第19题删除链表的倒数第N个结点

题目&#xff1a; 题解&#xff1a; func removeNthFromEnd(head *ListNode, n int) *ListNode {dummy : &ListNode{0, head}first, second : head, dummyfor i : 0; i < n; i {first first.Next}for ; first ! nil; first first.Next {second second.Next}second.N…

开启未来之门:Victoria VR 与 OpenAI 整合,引领 Web3 AI+AR 风潮

加密市场一直是科技创新的前沿阵地。虚拟现实&#xff08;VR&#xff09;技术和人工智能&#xff08;AI&#xff09;被认为是引领未来的重要技术之一&#xff0c;Web3 自然不会缺席这场足以改变人们生活方式的变革&#xff01; 2月份&#xff0c;Apple Vision Pro 的发售迅速引…

Jmeter的json提取器(包括提取一个参数的所有值,提取多个参数

jmeter的json提取器&#xff08;包括提取多个参数&#xff0c;提取一个参数的所有值&#xff09;https://www.cnblogs.com/jxial/p/15175314.html 在工作中经常遇到这种情况&#xff0c;就是下一个接口需要引用上一个接口返回的值&#xff0c;普遍的方法就是运用后置提取器 常…

智慧公厕中的大数据、云计算和物联网技术引领未来公厕管理革命

现代社会对于公共卫生和环境保护的要求越来越高&#xff0c;智慧公厕作为城市基础设施建设的重要组成部分&#xff0c;正引领着公厕管理的革命。随着科技的不断进步&#xff0c;大数据、云计算和物联网技术的应用为智慧公厕带来了全新的可能性&#xff0c;&#xff08;ZonTree中…

uniapp 上传视频到阿里云之后回显视频获取视频封面

uniapp 上传视频到阿里云之后回显视频获取视频封面 官网的解决方案 1.initial-time Number 指定视频初始播放位置&#xff0c;单位为秒&#xff08;s&#xff09;。 没什么卵用 2.使用 uni.createVideoContext(“myVideo”, this).seek(number)。 没什么卵用 <video :id&quo…

zabbix企业级监控平台

zabbix部署 安装源 重新创建纯净环境&#xff0c;利用base克隆一台虚拟机server1 给server1做快照&#xff0c;方便下次实验恢复使用 进入zabbix官网https://www.zabbix.com rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm …

Idea集成Docker的快捷部署

Idea集成Docker的快捷部署 配置Docker远程访问1.1 修改 `/lib/systemd/system/docker.service`1.2 替换`ExecStart`1.3 重启docker服务1.4 监听端口是否被占用1.5 服务器防火墙开启2375端口1.6 测试配置IDEA2.1 下载docker插件2.2 添加docker连接2.3 配置容器镜像加速器2.4 配置…

SQL注入sqli_labs靶场第二题

解题思路与第一题相同 ?id1 and 11 和?id1 and 12进行测试如果11页面显示正常和原页面一样&#xff0c;并且12页面报错或者页面部分数据显示不正常&#xff0c;那么可以确定此处为数字型注入。 联合查询&#xff1a; 猜解列名数量&#xff1a;3 ?id1 order by 4 判断回显…

南京航空航天大学-考研科目-513测试技术综合 高分整理内容资料-01-单片机原理及应用分层教程-单片机有关常识部分

系列文章目录 高分整理内容资料-01-单片机原理及应用分层教程-单片机有关常识部分 文章目录 系列文章目录前言总结 前言 单片机的基础内容繁杂&#xff0c;有很多同学基础不是很好&#xff0c;对一些细节也没有很好的把握。非常推荐大家去学习一下b站上的哈工大 单片机原理及…

【STL】list

目录 1. list的使用 1.1 list的构造 1.2 list iterator的使用 1.3 list capacity 1.4 list element access 1.5 list modifiers 1.6 list的迭代器失效 2. list的模拟实现 3. list与vector的对比 1. list的使用 1.1 list的构造 1.2 list iterator的使用 1. begin与end为…

性能优化原则

相关链接&#xff1a;【运行环境】加载资源的形式 性能优化 1 性能优化原则 多使用内存、缓存或其他方法 减少CPU计算量&#xff0c;减少网络加载耗时 &#xff08;适用于所有编程的性能优化----空间换时间&#xff09; 2 从何入手 性能优化-让加载更快 减少资源体积&#x…

java程序生成exe文件启动时,在没有java环境计算机运行

1.idea项目配置工件 2. 开始构建java程序成jar包 3. 生成exe启动程序 注&#xff1a;下面的输入框中写错了&#xff0c;应该是.\jre才对 4. 在已经选择的生成exe存放文件夹找到已经生成exe启动程序

你不可不知的5款小众神器

Hey小伙伴们&#x1f44b;&#xff0c;是不是还在为工作中的效率不高而烦恼呢&#xff1f;别急&#xff0c;今天我就给大家安利5款超实用的国产小众工作效软件&#xff0c;让你的工作台效率翻倍&#xff0c;轻松应对各种工作挑战&#xff01;&#x1f31f; 1️⃣ 亿可达 ycoda…

nexus搭建maven与docker镜像的私有仓库

引言 通过nexus搭建maven与docker镜像的私有仓库,实现jar包与镜像动态更新、共享、存储。 一、nexus部署 通过docker-compose部署nexus name: java services:#############################环境#############################env-nexus:restart: always## 3.58.1image: so…

Linux CPU利用率

Linux CPU利用率 在线上服务器观察线上服务运行状态的时候&#xff0c;绝大多数人都是喜欢先用 top 命令看看当前系统的整体 cpu 利用率。例如&#xff0c;随手拿来的一台机器&#xff0c;top 命令显示的利用率信息如下 这个输出结果说简单也简单&#xff0c;说复杂也不是那么…

技术解析:应对国内大流量攻击的新挑战与分布式清洗防御策略

近日&#xff0c;国内网络环境中出现的大流量攻击事件频发&#xff0c;且攻击规模呈指数级增长&#xff0c;部分攻击流量甚至超过了1.5Tbps。 这背后的主要原因是攻击者利用海外流量资源&#xff0c;通过复杂的网络技术和协议转换&#xff0c;将国际IPv4/IPv6流量巧妙伪装并转…

4.1Python的流程控制语句之分支语句

流程控制语句是计算机编程中用于控制程序执行流程的语句。它们允许根据条件来控制代码的执行顺序和逻辑&#xff0c;从而使程序能够根据不同的情况做出不同的决策。流程控制实现了更复杂和灵活的编程逻辑。 顺序语句 顺序语句是按照编写的顺序依次执行程序中的代码。代码会按照…

【测试开发学习历程】python迭代、可迭代对象、迭代器、生成器

1 迭代Iteration 迭代Iteration&#xff1a;所谓迭代就是重复运行一段代码语句块的能力&#xff0c;就好比在一个容器中进行一层一层遍历数据&#xff0c;在应用过程中for循环最为突出。迭代就是从某个容器对象中逐个地读取元素&#xff0c;直到容器中没有元素为止。迭代迭代&…