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 协议规…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...