RK Android11 WiFi模组 AIC8800 驱动移植流程
RK Android WiFi模组 AIC8800 驱动移植流程
- 作者:Witheart
- 更新时间:20250220
概要:本文介绍了基于 AIC8800D40 芯片的 WiFi6 模组 BL-M8800DS2-40 在 RK3568 平台上的驱动移植流程。主要涉及环境搭建、驱动代码分析、设备树修改、驱动编译配置、蓝牙库集成、wpa_supplicant 配置及 WiFi HAL 适配等内容,并提供详细的移植步骤和注意事项。
问题调试在另一篇文章:https://blog.csdn.net/Beihai_Van/article/details/145772085
1. 环境
- WiFi 模组:BL-M8800DS2-40(基于 AIC8800D40 芯片)
- CPU:RK3568
- OS:Android
2. WiFi芯片与WiFi模组的区别
- WiFi 芯片:核心部件,集成射频前端、基带处理器、数字信号处理等功能。
- WiFi 模组:基于 WiFi 芯片的完整无线通信组件,包含天线、外围电路、接口等。
AIC8800 属于 WiFi 芯片,而本次移植的 WiFi 模组是 BL-M8800DS2-40(基于 AIC8800D40)。
WiFi6 模组_必联(LB-LINK)官方网站

3. AIC8800 驱动代码包详解
3.1 驱动代码包结构
厂家送样后,需要获取最新的驱动代码包,并确保版本与模组匹配。驱动代码版本错误可能引发诸多问题。

3.2 Patch 注意事项
在 SDIO\patch\for_Rockchip\3566\Android11 目录下,提供了 Rockchip 平台的移植补丁(更像是移植成功的参考案例,不同wifi芯片还要具体配置),移植过程中需对比 mod 和 orig 文件夹的区别,可利用 git 进行差异分析。
在移植过程中需要注意一个问题:patch 仅仅指示了需要修改哪些文件以及具体的修改方法,但其中的驱动可能并不适用于你手头的模组。原因在于,官方提供的驱动包适用于多款模组,而 patch 仅是其中某款模组的案例,并且官方更新驱动时,并不会同步更新 patch 中的驱动。
因此,在移植时可以参考 patch 进行修改,但对于驱动适配系统的相关配置,一般无需更改。而对于新增的驱动文件,应在
driver_fw文件夹中查找正确的驱动文件进行添加,而不是直接使用 patch 中的文件。
3.3 Patch 使用方法
在使用 patch 进行移植时,主要是对比 mod 文件夹和 orig 文件夹的区别,然后在你的源码中进行相应的配置修改。直接手动对比可能比较繁琐,因此可以借助 Git 进行对比分析。
3.3.1. 初始化 Git 仓库
首先,在 orig 文件夹中初始化一个 Git 仓库.
接着,找到 mod 相比 orig 新增的文件,通常包含以下三部分:
- 模组固件:
- 主要是厂家编译好的二进制
.bin文件以及.txt配置文件。
- 主要是厂家编译好的二进制
- 模组驱动:
- 用于与内核交互,主要是
.c源码文件,编译后生成.ko驱动文件。
- 用于与内核交互,主要是
- 模组库:
- 例如
libbt之类的库,编译后生成.so共享库文件。
- 例如
3.3.2. 删除 mod 中的新增文件
由于我们只关心 源码的修改内容,而这些新增的二进制文件、驱动和库文件无需对比修改,仅需直接复制,所以应当先删除 mod 中的新增文件
原因:
- 这些新增文件会导致 Git 对比时产生大量无关内容,影响分析。
- 厂商在更新驱动时,不会同步更新
patch中的驱动,直接使用patch提供的驱动可能会导致 bug。
(别问为什么知道的,踩坑经验)
3.3.3. 进行 Git 对比
删除新增文件后,将 mod 文件夹的内容 覆盖 orig,然后使用 Git 进行对比:
⚠ VSCode 的 Git 对比 Bug
坑点提醒:
VSCode 的 Git 对比窗口 在路径长度超过 219 个字符 时,不会显示差异,容易导致遗漏修改。参考 Issue:
Git diff does not show files with long paths in Source Control View (Windows) #240770
4 设备树(DTS)修改
此处主要是参考RK官方文档去修改
01、Linux\Linux\Wifibt\Rockchip_Developer_Guide_Linux_WIFI_BT_CN.pdf
02、Android\android\wifi\Rockchip_Introduction_WIFI_Configuration_CN&EN.pdf
02、Android\common\MMC\Rockchip_Developer_Guide_SDMMC_SDIO_eMMC_CN.pdf
4.1 蓝牙部分
&wireless_bluetooth {compatible = "bluetooth-platdata";clocks = <&rk809 1>;clock-names = "ext_clock";uart_rts_gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;pinctrl-names = "default", "rts_gpio";pinctrl-0 = <&uart8m0_rtsn>;pinctrl-1 = <&uart8_gpios>;BT,reset_gpio = <&gpio3 RK_PD5 GPIO_ACTIVE_LOW>;status = "okay";
};wireless-bluetooth {uart8_gpios: uart8-gpios {rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;};
};
- 这里比较重要的是BT,reset_gpio,这个模块的34脚,PWR_BT,根据描述来看,高电平时蓝牙部分关闭,低电平时蓝牙部分开启
- 但是此部分的配置不一定是最终生效的版本,最终还要看驱动里是怎么处理的,有的驱动会对电平作反相处理,所以这部分可以GPIO_ACTIVE_LOW和GPIO_ACTIVE_HIGH都试试看
- UART 配置: 确保蓝牙与 CPU 通过 UART8 进行通信。
4.2 WiFi 部分
sdio_pwrseq: sdio-pwrseq {compatible = "mmc-pwrseq-simple";clocks = <&rk809 1>;clock-names = "ext_clock";pinctrl-names = "default";pinctrl-0 = <&wifi_enable_h>;/** On the module itself this is one of these (depending* on the actual card populated):* - SDIO_RESET_L_WL_REG_ON* - PDN (power down when low)*/post-power-on-delay-ms = <200>;reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
};
重点配置 WiFi reset-gpios,确保正确的电源控制。
wireless_wlan: wireless-wlan {compatible = "wlan-platdata";rockchip,grf = <&grf>;wifi_chip_type = "AIC8800";status = "okay";
};
此处的WiFi芯片名称的配置,应该和frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
这个文件中的
static wifi_device supported_wifi_devices[]中配置的名称一致(至少前三个字符要为AIC)
&sdmmc2 {max-frequency = <150000000>;supports-sdio;bus-width = <4>;disable-wp;cap-sd-highspeed;cap-sdio-irq;keep-power-in-suspend;mmc-pwrseq = <&sdio_pwrseq>;non-removable;pinctrl-names = "default";pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>;sd-uhs-sdr104;status = "okay";
};
- sd-uhs-sdr104表示支持sdio3.0
5. 驱动部分
-
添加驱动文件,也就是
SDIO\driver_fw\driver\aic8800下所有文件添加到
kernel\drivers\net\wireless\aic8800 -
然后在同级目录下的mk文件中添加编译选项,通过CONFIG_AIC_WLAN_SUPPORT宏定义控制是否编译aic8800/目录下的内容
kernel\drivers\net\wireless\Makefile
obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/
- 并且在同级目录下的kconfig中,引用aic8800/目录下的Kconfig文件,用于增加menuconfig中的aic8800驱动编译选项
source "drivers/net/wireless/aic8800/Kconfig"
- 配置内核编译配置文件kernel\arch\arm64\configs\rockchip_defconfig,请修改你实际上应用的内核编译配置文件
CONFIG_AIC_WLAN_SUPPORT=y
CONFIG_AIC_FW_PATH="/vendor/etc/firmware"
CONFIG_AIC8800_WLAN_SUPPORT=m
-
- CONFIG_AIC_WLAN_SUPPORT用于控制编译这个驱动
- CONFIG_AIC_FW_PATH用于配置模组固件存放的位置,固件最后会被复制到配置的这个位置
- CONFIG_AIC8800_WLAN_SUPPORT说明驱动将不会被编译进内核,而是以模块的形式动态插入(如果是以模块的形式动态插入,内核将根据sdio读到的vid和pid匹配不同的模块进行加载)
-
在
vendor\rockchip\common\wifi\wifi.mk文件中,添加编译出来的ko文件的路径,因为是动态加载ko文件的,所以ko文件编译出来后,将被复制到/vendor/lib/modules路径下进行动态加载
AIC_WIFI_KO_FILES := $(shell find $(TOPDIR)kernel/drivers/net/wireless/aic8800 -name "*.ko" -type f)
BOARD_VENDOR_KERNEL_MODULES += \
$(foreach file, $(AIC_WIFI_KO_FILES), $(file))
此处的配置用于找到编译出的ko文件
- 配置Android 启动时用于加载内核模块(.ko) 的配置文件
device\rockchip\common\init.insmod.cfg
加入
insmod /vendor/lib/modules/aic8800_bsp.ko
- 最终会编译出三个ko文件,分别是
aic8800_bsp.ko aic8800_btlpm.ko aic8800_fdrv.ko -
- aic8800_bsp用于模组的初始化等基础功能
- aic8800_fdrv用于WiFi
- aic8800_btlpm用于蓝牙
- 移植到RK Android平台时,实际上只加载aic8800_bsp.ko,aic8800_fdrv.ko
6. 蓝牙库 libbt

libbt用于完成对蓝牙模块硬件初始化与控制。
6.1 添加蓝牙库文件
将 driver_fw\aic\libbt\8800 目录下所有文件添加到 hardware\aic\aicbt\libbt 目录。
6.2 配置编译 libbt
- 在libbt同级目录下添加Android.mk,如果BOARD_HAVE_BLUETOOTH_AIC被配置了,那么子目录下所有makefile都生效
ifeq ($(BOARD_HAVE_BLUETOOTH_AIC),true)
LOCAL_PATH := $(call my-dir)
include $(call all-subdir-makefiles)
endif
而BOARD_HAVE_BLUETOOTH_AIC在device\rockchip\common\wifi_bt_common.mk这个mk文件中定义
BOARD_HAVE_BLUETOOTH_AIC := true
- 同样的,在libbt同级目录下添加aicbt.mk文件
CUR_PATH := hardware/aic/aicbtBOARD_HAVE_BLUETOOTH := truePRODUCT_PACKAGES += \libbt-vendor-aic
PRODUCT_PACKAGES += libbt-vendor-aic 定义了 libbt-vendor-aic 这个包,用于指定需要编译并包含到最终镜像
注意,此处有一个坑点,需要保证libbt中Android.mk中的LOCAL_MODULE与PRODUCT_PACKAGES一致,原厂的patch由于没有更新,这两者不一致
hardware\aic\aicbt\libbt\Android.mkLOCAL_MODULE := libbt-vendor-aic
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_OWNER := aic
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE 是用于定义模块名称,也就是最终会编译出libbt-vendor-aic.so这个模块。
7. wpa_supplicant 配置
7.1 wpa_supplicant 概念
wpa_supplicant 是一个用于管理 WiFi 连接的用户空间守护进程,主要负责:
- 处理 WPA/WPA2 认证
- 管理 WiFi 连接(扫描、连接、断开)
- 支持 WiFi Direct(P2P)
- 通过 socket 接口与 Android WiFi 框架交互
7.2 wpa_supplicant 具体配置
配置aic模块的wpa配置,设置aic模块的启动参数
device\rockchip\common\wpa_config.txt
添加
[aic]
/vendor/bin/hw/wpa_supplicant
-O/data/vendor/wifi/wpa/sockets
-puse_p2p_group_interface=1
-g@android:wpa_wlan0
-
[aic]:表示该配置适用于 AIC WiFi 模块。/vendor/bin/hw/wpa_supplicant:指定 wpa_supplicant 的可执行文件路径。-O/data/vendor/wifi/wpa/sockets:指定 wpa_supplicant 使用的 socket 目录,通常用于与其他组件(如 hostapd 或 Android WiFi 框架)通信。-puse_p2p_group_interface=1:启用 P2P 组接口支持,允许 WiFi Direct 功能。-g@android:wpa_wlan0:定义全局控制接口,@android:wpa_wlan0 允许 Android 通过 wpa_supplicant 进行 WiFi 控制
设置加载wpa_config.txt中的配置
external\wpa_supplicant_8\wpa_supplicant\main.c
#define AIC_MODULE_NAME "[aic]"else if (0 == strncmp(wifi_type, "AIC", 3)) {wpa_printf(MSG_INFO,"Start aic_wpa_supplicant\n");ret = read_wpa_param_config(AIC_MODULE_NAME,argv[1]);
}
WiFi芯片类型前缀为AIC时,加载对应的aic的wpa_supplicant参数。
8. WiFi HAL 配置
这部分主要是通过配置vid:pid,选择加载不同的库。
8.1 动态加载原理
sdio握手成功后,就会读到vid:pid,将读到的数值与已经配置vid:pid比较,动态加载不同的库
8.2 具体配置
vid:pid配置
frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
supported_wifi_devices 结构体数组中添加WiFi名称以及对应的vid:pid
{"AIC8800", "5449:0145"},
- 这里又有一个坑点,patch中提供的这个vid:pid不适用于我这个模组,需要具体配置。
- 获取真正的vid:pid有两种方式,一种是如果WiFi模组正常上电且sdio握手成功,那么是可以通过读/sys/bus/sdio/devices下的设备目录下的uevent文件得到的
rk3568_HW:/ # cat /sys/bus/sdio/devices/
mmc3:390b:1/ mmc3:390b:2/
rk3568_HW:/ # cat /sys/bus/sdio/devices/mmc3\:390b\:1/uevent
DRIVER=aicwf_sdio
SDIO_CLASS=07
SDIO_ID=C8A1:0082
MODALIAS=sdio:c07vC8A1d0082
rk3568_HW:/ # cat /sys/bus/sdio/devices/mmc3\:390b\:2/uevent
DRIVER=aicbsp_sdio
SDIO_CLASS=07
SDIO_ID=C8A1:0182
MODALIAS=sdio:c07vC8A1d0182
这个WiFi模组扫卡成功后可以读到两个mmc设备,分别是mmc3:390b:1/ mmc3:390b:2/,
读取到的mmc3:390b:1设备的vid:pid为C8A1:0082,那么增加这个vid:pid到rk_wifi_ctrl.cpp中即可。
- 二是直接向厂家询问,或在驱动包中寻找
接下来是检测流程,调用check_wifi_chip_type_string(wifi_type)函数,尝试获取wifi芯片类型,保存到wifi_type
frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
int check_wifi_chip_type_string(char *type)
{if (identify_sucess == -1) {if (get_wifi_device_id(SDIO_DIR, PREFIX_SDIO) == 0)PLOG(DEBUG) << "SDIO WIFI identify sucess";else if (get_wifi_device_id(USB_DIR, PREFIX_USB) == 0)PLOG(DEBUG) << "USB WIFI identify sucess";else if (get_wifi_device_id(PCIE_DIR, PREFIX_PCIE) == 0)PLOG(DEBUG) << "PCIE WIFI identify sucess";else {PLOG(DEBUG) << "maybe there is no usb wifi or sdio or pcie wifi,set default wifi module Brocom APXXX";strcpy(recoginze_wifi_chip, "APXXX");identify_sucess = 1 ;}}strcpy(type, recoginze_wifi_chip);PLOG(ERROR) << "check_wifi_chip_type_string : " << type;return 0;
}
还未进行识别时,identify_sucess为-1,此时开始使用get_wifi_device_id()获取设备id,依次尝试sdio、usb、pcie设备
get_wifi_device_id()函数中,通过读uevent获取vid:pid,然后用一个for循环,比较已经在supported_wifi_devices中添加的设备vid:pid与读到的vid:pid,有相符的,就将对应的wifi芯片名称复制到recoginze_wifi_chip中,get_wifi_device_id()执行完成之后,会将recoginze_wifi_chip复制到type中,也就是wifi_type。
接下来配置动态加载不同的库
- 在
frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp中,有一个wifi_load_driver()函数,调用了check_wifi_chip_type_string(wifi_type)函数,尝试获取wifi芯片类型wifi_type - 需要添加wifi ko驱动的路径,以及驱动与wifi类型的对应
wifi_hal_common.cpp
#define AIC8800_DRIVER_MODULE_PATH WIFI_MODULE_PATH"aic8800_fdrv.ko"
#define AIC8800_DRIVER_MODULE_NAME "aic8800_fdrv"
wifi_ko_file_name module_list[] ={{"AIC8800", AIC8800_DRIVER_MODULE_NAME, AIC8800_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},
}
- 定义蓝牙使用的库
在hardware\interfaces\bluetooth\1.0\default\vendor_interface.cc中
static const char* VENDOR_AIC_LIBRARY_NAME = "libbt-vendor-aic.so";
然后根据wifi芯片类型,得到要加载的库的名称
if ((0 == strncmp(wifi_type, "AIC", 3))) {ALOGE("%s try to open %s \n", __func__, VENDOR_AIC_LIBRARY_NAME);strcpy(vendor_lib_name, VENDOR_AIC_LIBRARY_NAME);
}
根据这个名称进行加载
lib_handle_ = dlopen(vendor_lib_name, RTLD_NOW);
- 根据 Wi-Fi 芯片类型来确定应该使用哪个Wi-Fi 直连(P2P)接口名称
hardware\interfaces\wifi\1.4\default\wifi_chip.cpp
std::string getP2pIfaceName() {std::array<char, PROPERTY_VALUE_MAX> buffer;if (wifi_type[0] == 0) {check_wifi_chip_type_string(wifi_type);}if (0 == strncmp(wifi_type, "AP", 2) || 0 == strncmp(wifi_type, "AIC", 3)) {property_set("vendor.wifi.direct.interface", "p2p-dev-wlan0");property_get("wifi.direct.interface", buffer.data(), "p2p-dev-wlan0");} else {property_set("vendor.wifi.direct.interface", "p2p0");property_get("wifi.direct.interface", buffer.data(), "p2p0");}return buffer.data();
}
注:此处的AP应该是AP系列WiFi芯片的意思
9. 固件添加
-
主要是厂家编译好的二进制 .bin 文件以及 .txt 配置文件。
-
将厂家给的驱动包中
driver_fw\fw下具体的固件放置在vendor\rockchip\common\wifi\firmware下。 -
BL-M8800DS2-40使用driver_fw\fw\aic8800D80目录下的固件。
至此,驱动配置成功,但是在调试过程中还遇到一些问题,详情见另一篇文章。
相关文章:
RK Android11 WiFi模组 AIC8800 驱动移植流程
RK Android WiFi模组 AIC8800 驱动移植流程 作者:Witheart更新时间:20250220 概要:本文介绍了基于 AIC8800D40 芯片的 WiFi6 模组 BL-M8800DS2-40 在 RK3568 平台上的驱动移植流程。主要涉及环境搭建、驱动代码分析、设备树修改、驱动编译配…...
深度学习-6.用于计算机视觉的深度学习
Deep Learning - Lecture 6 Deep Learning for Computer Vision 简介深度学习在计算机视觉领域的发展时间线 语义分割语义分割系统的类型上采样层语义分割的 SegNet 架构软件中的SegNet 架构数据标注 目标检测与识别目标检测与识别问题两阶段和一阶段目标检测与识别两阶段检测器…...
免费送源码:ava+springboot+MySQL 基于springboot 宠物医院管理系统的设计与实现 计算机毕业设计原创定制
摘 要 在当今社会,宠物已经成为人们生活中不可或缺的一部分,因此宠物健康和医疗问题也备受关注。为了更好地管理宠物医院的日常运营和提供优质的医疗服务,本研究设计并实现了一套基于Spring Boot框架的宠物医院管理系统。这一系统集成了多项功…...
【电机控制器】ESP32-C3语言模型——DeepSeek
【电机控制器】ESP32-C3语言模型——DeepSeek 文章目录 [TOC](文章目录) 前言一、简介二、代码三、实验结果四、参考资料总结 前言 使用工具: 提示:以下是本篇文章正文内容,下面案例可供参考 一、简介 二、代码 #include <Arduino.h&g…...
小型字符级语言模型的改进方向和策略
小型字符级语言模型的改进方向和策略 一、回顾小型字符级语言模型的处理流程 前文我们已经从零开始构建了一个小型字符级语言模型,那么如何改进和完善我们的模型呢?有哪些改进的方向?我们先回顾一下模型的流程: 图1 小型字符级语言模型的处理流程 (1)核心模块交互过程:…...
力扣-贪心-56 合并区间
思路 先按照左区间进行排序,然后初始化left和right,重叠时,更新right,不重叠时,收集区间 代码 class Solution { public:static bool cmp(vector<int> a, vector<int> b){if(a[0] b[0]){return a[1] &…...
vue 3D 翻页效果
<template><view class"swipe-container" touchstart"onTouchStart" touchmove"onTouchMove" touchend"onTouchEnd"><view class"page">初始页</view></view> </template><script&g…...
【系列专栏】银行信息系统研发外包风险管控-08
银行信息系统研发外包风险管控 在金融科技日新月异的当下,银行业务对信息系统的依赖程度与日俱增。为了充分利用外部专业资源,提升研发效率并合理控制成本,许多银行选择将信息系统研发外包。然而,这一策略在带来诸多便利的同时&a…...
[ComfyUI] 【AI】如何获得一张人物图片的优质描述
在使用ComfyUI时,获取一张人物图片的优质英文描述非常重要,尤其是在涉及图像生成、自动化标签和多模态AI任务时。以下是一个简单的流程,可以帮助你快速从一张人物图片中提取出精确且高质量的英文描述。 1. 打开 Hugging Face 网站 首先,您需要访问 Hugging Face 提供的 J…...
深度学习基础--ResNet网络的讲解,ResNet50的复现(pytorch)以及用复现的ResNet50做鸟类图像分类
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 前言 如果说最经典的神经网络,ResNet肯定是一个,这篇文章是本人学习ResNet的学习笔记,并且用pytorch复现了ResNet50&…...
stack,queue,priority_queue学习知识点
容器适配器 在c常用的容器中,有的是以容器迭代器为核心,而有的则以容器适配器为核心。较为常用的就包括queue和stack。接下来我将简单的以queue和stack的模拟实现介绍其特点。 在以下的模拟实现中,class Con就是我们的容器适配器࿰…...
css特异性,继承性
html <div class"introduce"><div class"title">介绍</div><div class"card-box"><div class"card"><div class"title">管理</div></div></div> </div> scs…...
力扣hot100刷题——11~20
文章目录 11.滑动窗口最大值题目描述思路:滑动窗口单调队列code 12.最小覆盖子串题目描述思路:双指针/滑动窗口哈希code Ⅰcode Ⅱ 13.最大子数组和题目描述思路:dp/贪心code 14.合并区间题目描述思路:贪心code 15.轮转数组题目描…...
R语言Stan贝叶斯空间条件自回归CAR模型分析死亡率多维度数据可视化
全文链接:https://tecdat.cn/?p40424 在空间数据分析领域,准确的模型和有效的工具对于研究人员至关重要。本文为区域数据的贝叶斯模型分析提供了一套完整的工作流程,基于Stan这一先进的贝叶斯建模平台构建,帮助客户为空间分析带来…...
速通HTML
目录 HTML基础 1.快捷键 2.标签 HTML进阶 1.列表 a.无序列表 b.有序列表 c.定义列表 2.表格 a.内容 b.合并单元格 3.表单 a.input标签 b.单选框 c.上传文件 4.下拉菜单 5.文本域标签 6.label标签 7.按钮标签 8.无语义的布局标签div与span 9.字符实体 HTML…...
安装 Milvus Java SDK
本主题介绍如何为 Milvus 安装 Milvus Java SDK。 当前版本的 Milvus 支持 Python、Node.js、GO 和 Java SDK。 要求 Java(8 或更高版本)Apache Maven 或 Gradle/Grails 安装 Milvus Java SDK 运行以下命令安装 Milvus Java SDK。 Apache Maven &…...
云手机如何进行经纬度修改
云手机如何进行经纬度修改 云手机修改经纬度的方法因不同服务商和操作方式有所差异,以下是综合多个来源的常用方法及注意事项: 通过ADB命令注入GPS数据(适用于技术用户) 1.连接云手机 使用ADB工具连接云手机服务器,…...
牛客周赛 Round 82(思维、差分、树状数组、大根堆、前后缀、递归)
文章目录 牛客周赛 Round 82(思维、差分、树状数组、大根堆、前后缀、递归)A. 夹心饼干B. C. 食堂大作战(思维)D. 小苯的排列计数(差分、树状数组)E. 和和(大根堆,前缀和)F. 怎么写线性SPJ &…...
MQTT实现智能家居------2、写MQTT程序的思路
举个最简单的例子: 手机------服务器-------家具 我们这里只看手机和家具的客户端: 手机:1)需要连接服务器 2)需要发布指令给服务器到家里的家具 3)接受来自于家里家具的异常状况 4)保持心…...
大模型面试问题准备
1. BERT的多头注意力为什么需要多头? 为了捕捉不同子空间的语义信息,每个头关注不同的方面,增强模型的表达能力 2. 什么是softmax上下溢出问题? 问题描述: 上溢出:ye^x中,如果x取非常大的正数…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
