Android8.1 hal 加载wifi ko模块流程
Android如果发现wifi没有正常启动,从下面两个方面
1.是否正常编译出wifi ko文件,如果没有,说明编译的有问题,ko文件的地址vendor/lib/module/devices/wifi
2.如果有编译出ko文件,但还提示Wifi HAL start failed之类的,先使用insmod手动加载ko文件,查看wifi是否能正常启动,如果可以,说明ko文件没有成功加载,如下方法查找原因
Android启动的时候会去加载wifi模块,这时候这部分代码在frameworks\opt\net\wifi\libwifi_hal\,这部分的代码主要的功能为,大概内容为通过读取uevnt的获取到系统下的wifi模块的vip和pid,从而从代码的列表中查找到是那个一个wifi模块,然后又从列表中获取wifi模块的驱动代码在那里,从而调用insmod xxxx.ko加载wifi模块。
frameworks\opt\net\wifi\libwifi_hal\rk_wifi_ctrl.cpp
static wifi_device supported_wifi_devices[] = {{"RTL8188EU", "0bda:8179"},{"RTL8188EU", "0bda:0179"},{"RTL8723BU", "0bda:b720"},{"RTL8723BS", "024c:b723"},{"RTL8822BS", "024c:b822"},{"RTL8723CS", "024c:b703"},{"RTL8723DS", "024c:d723"},{"RTL8188FU", "0bda:f179"},{"RTL8822BU", "0bda:b82c"},{"RTL8189ES", "024c:8179"},{"RTL8189FS", "024c:f179"},{"RTL8192DU", "0bda:8194"},{"RTL8812AU", "0bda:8812"},{"SSV6051", "3030:3030"},{"ESP8089", "6666:1111"},{"AP6354", "02d0:4354"},{"AP6330", "02d0:4330"},{"AP6356S", "02d0:4356"},{"AP6335", "02d0:4335"},{"AP6255", "02d0:a9bf"},{"RTL8822BE", "10ec:b822"},{"MVL88W8977", "02df:9145"},
};frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cpp//wifi模块的驱动ko,文件的路径地址"/vendor/lib/modules/"
#define WIFI_MODULE_PATH "/vendor/lib/modules/"
wifi_ko_file_name module_list[] =
{{"RTL8723BU", RTL8723BU_DRIVER_MODULE_NAME, RTL8723BU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8188EU", RTL8188EU_DRIVER_MODULE_NAME, RTL8188EU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8192DU", RTL8192DU_DRIVER_MODULE_NAME, RTL8192DU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8822BU", RTL8822BU_DRIVER_MODULE_NAME, RTL8822BU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8822BS", RTL8822BS_DRIVER_MODULE_NAME, RTL8822BS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8188FU", RTL8188FU_DRIVER_MODULE_NAME, RTL8188FU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8189ES", RTL8189ES_DRIVER_MODULE_NAME, RTL8189ES_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8723BS", RTL8723BS_DRIVER_MODULE_NAME, RTL8723BS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8723CS", RTL8723CS_DRIVER_MODULE_NAME, RTL8723CS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8723DS", RTL8723DS_DRIVER_MODULE_NAME, RTL8723DS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8812AU", RTL8812AU_DRIVER_MODULE_NAME, RTL8812AU_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8189FS", RTL8189FS_DRIVER_MODULE_NAME, RTL8189FS_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"RTL8822BE", RTL8822BE_DRIVER_MODULE_NAME, RTL8822BE_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"SSV6051", SSV6051_DRIVER_MODULE_NAME, SSV6051_DRIVER_MODULE_PATH, SSV6051_DRIVER_MODULE_ARG},{"ESP8089", ESP8089_DRIVER_MODULE_NAME, ESP8089_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"AP6335", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"AP6330", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"AP6354", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"AP6356S", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"AP6255", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"APXXX", BCM_DRIVER_MODULE_NAME, BCM_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"MVL88W8977", MVL_DRIVER_MODULE_NAME, MVL_DRIVER_MODULE_PATH, MVL88W8977_DRIVER_MODULE_ARG},{"RK912", RK912_DRIVER_MODULE_NAME, RK912_DRIVER_MODULE_PATH, UNKKOWN_DRIVER_MODULE_ARG},{"UNKNOW", DRIVER_MODULE_NAME_UNKNOW, DRIVER_MODULE_PATH_UNKNOW, UNKKOWN_DRIVER_MODULE_ARG}};
hardware\interfaces\wifi\1.2\default\service.cpp
//加载 WifiModeController然后会调用到WifiModeController::WifiModeController()
android::sp<android::hardware::wifi::V1_2::IWifi> service =new android::hardware::wifi::V1_2::implementation::Wifi(std::make_shared<WifiLegacyHal>(),std::make_shared<WifiModeController>(), std::make_shared<WifiFeatureFlags>());hardware\interfaces\wifi\1.2\default\wifi_mode_controller.cpp
WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}bool WifiModeController::initialize() {if (!driver_tool_->LoadDriver()) { //调用到下面的 LoadDriverLOG(ERROR) << "Failed to load WiFi driver";return false;}return true;
}加载wifi驱动代码调用路径
frameworks\opt\net\wifi\libwifi_hal\driver_tool.cppbool DriverTool::LoadDriver()return ::wifi_load_driver()wifi_load_driver() //frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cppcheck_wifi_chip_type_string //frameworks\opt\net\wifi\libwifi_hal\wifi_hal_common.cppif (!strcmp(wifi_type , module_list[i].wifi_name)) {wifi_ko_path = module_list[i].wifi_module_path; //从module_list中获取到wifi驱动,xxxx.ko的路径,在这里是"/vendor/lib/modules/xxxx.ko" wifi_ko_arg = module_list[i].wifi_module_arg;}save_wifi_chip_type(wifi_type); //保存我们加载wifi的一些信息,这些信息用来给wpa_supplicant加载对于的wifi启动参数。insmod(wifi_ko_path, wifi_ko_arg); //加载ko模块,和我们手动命令insmod xxxx.ko效果一样的//此功能为了从supported_wifi_devices这个列表里面获取当前SDIO上面挂载的是那个模块
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); //复制supported_wifi_devices里面的wifi_name的值PLOG(ERROR) << "check_wifi_chip_type_string : " << type;return 0;
}
wifi启动驱动加载fw流程
现在的wifi模块启动的时候都要加载一个fw固件,这个固件是做什么用的呢?可能是厂商用来做一下差异配置把,或者是加载射频参数进行使用,大家可以理解为加载一个bin文件到wifi模组中,每次wiif模组上电的时候都需要加载一次,加载的操作在wifi驱动的加载的时候,不同的厂商加载的bin文件不一样,下面我们可以通过系统启动的时候打印的log可以看到如下打印,下面的例子是博通的wifi模组的打印,Realtek不一样
博通wifi加载过程
Final fw_path=/vendor/etc/firmware/fw_bcm43438a1.bin
[ 64.276445] Final nv_path=/vendor/etc/firmware/nvram_ap6212a.txt
[ 64.276669] Final clm_path=/vendor/etc/firmware/clm.blob
[ 64.276896] Final conf_path=/vendor/etc/firmware/config.txt
[ 64.279224] dhd_os_open_image: /vendor/etc/firmware/fw_bcm43438a1.bin (414665 bytes) open success
[ 64.365150] dhd_os_open_image: /vendor/etc/firmware/nvram_ap6212a.txt (1003 bytes) open success
[ 64.365249] NVRAM version: AP6212A_NVRAM_V1.0.1_20160606grep "Final fw_path=" -nr
通过查找Final fw_path=查找出在那里打印出的log,从而找到。
kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c:8341: printf("Final fw_path=%s\n", bus->fw_path);
所以可以知道在驱动里面会加载fw固件,但是这个固件的地址是在那里传进来的需要进一步追踪bus->fw_path这个值。
经过追踪发现在rockchip这个平台,固件的路径在内核里面写死了,代码在kernel\drivers\net\wireless\rockchip_wlan\rkwifi\rk_wifi_config.c里面定义了一个函数int rkwifi_set_firmware(char *fw, char *nvram),这个函数在博通的wifi驱动里面被调用,从而获取wifi固件的烧录地址,kernel\drivers\net\wireless\rockchip_wlan\rkwifi\bcmdhd\dhd_linux.c的bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)中被调用。
对于博通的wifi和蓝牙二和一芯片来说一般需要加载3个固件分别对应给wifi和蓝牙使用的:
对于wifi部分有fw_bcm43438a1.bin和nvram_ap6212a.txt
对于蓝牙部分的固件有
bcm43438a1.hcd
对于Realtek的wifi,wifi部分不需要加载固件,但是蓝牙需要加载固件,固件的地址在kernel\drivers\bluetooth\rtk_btusb.c里面定义
static patch_info fw_patch_table[] = {
/* { vid, pid, lmp_sub_default, lmp_sub, everion, mp_fw_name, fw_name, config_name, fw_cache, fw_len, mac_offset } */
{ 0x0BDA, 0x1724, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* RTL8723A */
{ 0x0BDA, 0x8723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE */
{ 0x0BDA, 0xA723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE for LI */
{ 0x0BDA, 0x0723, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE */
{ 0x13D3, 0x3394, 0x1200, 0, 0, "mp_rtl8723a_fw", "rtl8723a_fw", "rtl8723a_config", NULL, 0 ,CONFIG_MAC_OFFSET_GEN_1_2, MAX_PATCH_SIZE_24K}, /* 8723AE for Azurewave*/
蓝牙加载驱动的时候内核层会调用request_firmware(&cfg, config_name, &udev->dev);来下载固件。
request_firmware使用方法可以参考:https://blog.csdn.net/magod/article/details/6049558。
当内核调用request_firmware这个函数的时候,在应用层就会在这个目录/sys/class/firmware生成一个节点,这个节点由三个属性分为为:
loading
这个属性应当被加载固件的用户空间进程设置为 1. 当加载进程完成, 它应当设为 0. 写一个值 -1 到 loading 会中止固件加载进程.data
data 是一个二进制的接收固件数据自身的属性. 在设置 loading 后, 用户空间进程应当写固件到这个属性.device
这个属性是一个符号连接到 /sys/devices 下面的被关联入口项.
所有由此推测,需要下载蓝牙固件的时候,应用层一定会往data这个属性写入固件的数据。
android hal 加载wpa_supplicant流程
我们前面的《android hal 加载wifi ko模块流程》中已经说明了,系统启动后会获取到 wifi 芯片 vid pid 加载相应的wifi ko驱动,然后在加载ko驱动的同时保存wifi芯片的一些信息,比如我们加载的wifi模块是博通Broadcom的就保存好博通Broadcom wifi的名字等信息,如果是加载的模块是瑞昱(Realtek)的就保存瑞昱(Realtek)wifi名字的信息。之后系统会启动之后系统会读取init.connectivity.rc 这个脚本,这个脚本会启动wpa_supplicant这个服务,这个应用服务会常驻在后台,启动wpa_supplicant的时候需要指定wifi模块的参数,参数保存在“/vendor/etc/wifi/wpa_config.txt”,源码目录放在/device/rockchip/common/wpa_config.txt。
librkwifi-ctrl.so从那里来?
在\frameworks\opt\net\wifi\libwifi_hal\Android.bp
cc_library_shared { //编译成可执行文件,cc_library_shared编译成动态库name: "librkwifi-ctrl", //生成librkwifi-ctrl.so库vendor: true, //编译出来放在/vendor目录下(默认是放在/system目录下)cflags: wifi_hal_cflags,local_include_dirs: ["include"], //用户值定的头文件查找路径shared_libs: ["libbase"], //编译依赖的动态库 header_libs: ["libcutils_headers"],srcs: ["rk_wifi_ctrl.cpp"], //源文件,格式["a.cpp", "b.cpp"]
}
相关文章:
Android8.1 hal 加载wifi ko模块流程
Android如果发现wifi没有正常启动,从下面两个方面 1.是否正常编译出wifi ko文件,如果没有,说明编译的有问题,ko文件的地址vendor/lib/module/devices/wifi 2.如果有编译出ko文件,但还提示Wifi HAL start failed之类的…...
Unity SteamVR 开发教程:SteamVR Input 输入系统(2.x 以上版本)
文章目录 📕前言📕教程说明📕导入 SteamVR 插件📕SteamVR Input 窗口⭐action.json 文件⭐窗口面板⭐SteamVR_Input 目录 📕SteamVR 动作的类型⭐Boolean⭐Single⭐Vector2⭐Vector3⭐Pose⭐Skeleton⭐Vibration &…...
PyTorch中,卷积层、池化层、转置卷积层输出特征图形状计算公式总结
在PyTorch中,卷积层(Convolutional Layer)、池化层(Pooling Layer,例如最大池化层)、以及转置卷积层(Transpose Convolutional Layer,也称为反卷积层或上采样层)的输出特…...
Git Cherry Pick命令
1. 简介 Git是一款分布式版本控制系统,它提供了许多强大的功能来管理代码的版本和变更。其中之一就是cherry-pick命令,它允许我们选择某个分支上的一个或多个提交,并将它们应用到当前分支上。这个功能非常有用,可以帮助我们在不合…...
算法:经典贪心算法--跳一跳[2]
1、题目: 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处: 返回到达 nums[n - 1] 的最小跳跃次数。生…...
Vue 和 React 前端框架的比较
一、什么是Vue? Vue[1] 是一个用于构建用户界面的渐进式、可逐步采用的 JavaScript 框架。它由 Evan You[2] 于 2014 年创建,并由一个活跃的开发者社区负责维护。 Vue 设计得非常轻量级、灵活和强大。它建立在一个基于组件的架构上,以组件为…...
【Java】什么是过滤器链(FilterChain )?哪些场景可以使用过滤器链?
文章目录 前言1、创建过滤器2、修改 web.xml3、运行项目并查看结果 前言 在一个 Web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个…...
Vue-video-player下载失败(npm i 报错)
Vue-video-player下载失败 最近在做项目时涉及到视频的播放组件,看了一下选择了Vue-video-player这个工具,实际在操作中是遇到许多问题的。 Q1:不支持谷歌 对于 “vue-video-player” 使用时出现 Adobe Flash 不再支持的提示,这是因为 Ado…...
数据在内存中的存储(1)
目录 1、整数在内存中的存储 原码、反码、补码: 2、大小端: 前提须知: 大小端存储方式: 字节的顺序: 概念: 判断机器是大端还是小端: 代码展示: 代码优化1.0: …...
LINUX常用命令练习
显示LINUX系统当前的日期和时间。 date以 yyyy/mm/dd的格式显示系统当前的日期 date %Y/%m/%d以 yyyy-mm-dd的格式显示系统当前的日期 date %Y-%m-%d查看在线用户信息 who显示当前月份的日历 cal显示2023年整年的日历 cal 2023显示2023年9月的日历 cal 9 2023查看LINUX系统的Sh…...
2022年全国研究生数学建模竞赛华为杯C题汽车制造涂装-总装缓存调序区调度优化问题求解全过程文档及程序
2022年全国研究生数学建模竞赛华为杯 C题 汽车制造涂装-总装缓存调序区调度优化问题 原题再现: 背景介绍 汽车制造厂主要由焊装车间、涂装车间、总装车间构成,每个车间有不同的生产偏好,如:焊装车间由于车身夹具的限制偏向最…...
文本直接生成3D游戏场景、功能,用ChatGPT方式开发游戏!
3D游戏开发平台Hiber3D通过谷歌的PaLM大语言模型,结合自身500多个模板库,以及数百万个成品3D场景进行微调,推出了一个全新游戏开发平台。 该平台在生成式AI加持下,用户可以像使用ChatGPT那样,通过文本问答方式快速创建…...
2023年会展行业研究报告
第一章 行业概况 1.1 定义 会展行业是一个多元化和复杂的领域,涵盖了许多不同的活动和功能。一般来说,会展业是指在一定的区域空间内,许多人聚集在一起形成的定期或者不定期,制度或者非制度,传递和交流信息的群众性的…...
【Redis】如何保证Redis缓存与数据库的一致性?
文章目录 1、四种同步策略2、更新缓存还是删除缓存2.1 更新缓存2.2 删除缓存 3、先操作数据库还是缓存3.1 先删除缓存再更新数据库3.2 先更新数据库再删除缓存 4、延时双删4.1 采用读写分离的架构怎么办? 5、利用消息队列进行删除的补偿 1、四种同步策略 想要保证缓…...
MATLAB中ischange函数用法
目录 语法 说明 示例 均值的变化 线性区的变化 矩阵数据 ischange函数的功能是查找数据中的突然变化。 语法 TF ischange(A) TF ischange(A,method) TF ischange(___,dim) TF ischange(___,Name,Value) [TF,S1] ischange(___) [TF,S1,S2] ischange(___) 说明 …...
【React + Ant Design】表单如何在前置项未填写时禁止后置项交互并提示
在 react antd 中,对表单做在前置项未填写时禁用后置项交互并提示的效果。 情景 最近有这么个需求,某个业务中,要填写一张表单,其中有这样两项:选择数据连接和选择数据表,数据表是数据连接下所拥有的表。…...
Linux学习之MySQL建表
MySQL查询1 MySQL查询2 表管理 #1. 建库#1)库名命名规则仅可以使用数字、字母、下划线、不能纯数字,区分字母大小写,具有唯一性,不可使用MySQL命令或特殊字符#创建数据表时可以查看一下默认的字符集,8.0后创建数据库…...
Redis哨兵集群的介绍及搭建
Redis 是一款开源的、内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。然而,作为一个单点服务,Redis 在面临硬件故障或者网络问题时可能会导致服务不可用。为了解决这个问题,Redis 提供了哨兵模式,一个…...
【zookeeper】zookeeper日常运维
本文将分享一些zookeeper在日常使用中一些维护经验。 zookeeper清理快照 脚本或者命令清理 zookeeper长时间运行,快照逐渐增多可能造成服务器磁盘被占满的情况,但我们不能贸然用rm命令删除快照文件,如果直接删完会导致丢失好多数据&#x…...
【工作记录】MQTT介绍、安装部署及springboot集成@20230912
背景 近期公司可能会有物联网设备相关项目内容,提前对用到的mqtt协议做预研和初步使用。 最初接触到mqtt协议应该是早些年的即时通讯吧,现在已经是物联网设备最热门的协议了。 作为记录,也希望能帮助到需要的朋友。 MQTT介绍 《MQTT 协议规…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
