RK356x bsp 5 - 海华AW-CM358SM Wi-Fi/Bt模组调试记录
文章目录
- 1、环境介绍
- 2、目标
- 3、海华AW-CM358SM
- 3.1、基本信息
- 3.2、支持SDIO3.0
- 3.3、电气特性
- 4、适配流程步骤
- 5、SDIO控制器适配
- 5.1、sdio dts配置
- 5.2、验证
- 6、Wi-Fi 适配
- 6.1、wifi dts配置
- 6.2、驱动移植
- 6.2.1、kernel menuconfig
- 6.2.2、传统驱动移植
- 6.2.3、RK SDK WIFI/BT驱动独立编译
- 6.3、Wi-Fi 功能验证
- 6.3.1、加载驱动
- 6.3.2、STA模式测试
- 6.3.3、AP测试
- 7、蓝牙适配
- 7.1、bt dts配置
- 7.2、驱动移植
- 7.3、蓝牙功能验证
- 7.3.1、使能蓝牙设备
- 7.3.2、扫描外设
- 7.3.3、开发板发送文件给安卓手机
1、环境介绍
硬件:飞凌ok3568-c开发板
软件:原厂rk356x sdk
2、目标
调试海华AW-CM358SM WIFI/BT模组,可以正常上网、使用蓝牙。
3、海华AW-CM358SM
3.1、基本信息

- 主芯片:NXP的88W8987
- Wi-Fi接口:SDIO
- BT接口:UART
3.2、支持SDIO3.0

3.3、电气特性
AW-CM358SM的VDDIO为1.8V:



所以,RK3568的SDIO接口的工作电压也要是1.8V,请检查设备树电源域&pmu_io_domains节点vccio6是否配置为1.8v(同时,SDIO3.0模式必须为1.8v):


4、适配流程步骤
- 配置设备树,让SDIO控制器工作。
- 配置设备树,让SDIO控制器可以发现WIFI/BT模组。
- Wi-Fi适配:配置设备树,移植设备驱动。
- 验证Wi-Fi功能。
- 蓝牙适配:配置设备树。
- 验证蓝牙功能。
5、SDIO控制器适配
现在先解决“适配流程步骤”的第1,第2点。即让SDIO控制器工作,且可以扫到WIFI卡。
5.1、sdio dts配置
从下面两幅原理图可以得出:
- WIFI模组的WIFI_REG_ON引脚接到了RK3568的GPIO3_D4。
- WIFI模组的SDIO接口接到了RK3568的SDMMC2接口。


设备树配置如下:
/* WL_REG_ON 由 sdio_pwrseq 节点进行管理控制 */
&sdio_pwrseq {compatible = "mmc-pwrseq-simple";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>;/* 这里配置的是WL_REG_ON引脚 */reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
};&pinctrl {sdio-pwrseq {wifi_enable_h: wifi-enable-h {/* 这里配置的是WL_REG_ON引脚 */rockchip,pins = <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; };};
};/* SDIO接口Wi-Fi专用配置:SDIO接口节点 */
&sdmmc2 {max-frequency = <150000000>; /* sdio接口的最大频率,可调整 */supports-sdio;bus-width = <4>; /* 4线模式,可调整1线模式 */disable-wp;cap-sd-highspeed;cap-sdio-irq;keep-power-in-suspend;mmc-pwrseq = <&sdio_pwrseq>; /* WL_REG_ON 管理 */non-removable;pinctrl-names = "default";pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>;sd-uhs-sdr104; /* 支持SDIO3.0 */status = "okay";
};
5.2、验证
- 查看 log:
dmesg | grep "fe000000"

dmesg | grep "mmc3"

- 查看
/sys/bus/mmc/devices/目录下的sdio设备:
ls /sys/bus/mmc/devices/

mmc3:0001对应的基址是fe000000,可以回到设备树查看,就是sdmmc2接口:

如果没有如上对应的log输出,/sys/bus/mmc/devices/目录下也没出现对应的sdio设备,说明sdio控制器没有扫到wifi卡,请重新检查设备树配置和对应PIN脚的电平状态及CLK频率是否正确。
6、Wi-Fi 适配
现在SDIO控制器可以识别到WiFi卡,但是还没有wlan节点出来,因为还没有驱动。
6.1、wifi dts配置
从下面原理图可以得出:
- WIFI模组的WIFI_HOST_WAKE_B引脚接到了RK3568的GPIO0_D4。

设备树继续添加wlan节点,同时配置pinctrl节点:
&wireless_wlan {compatible = "wlan-platdata";rockchip,grf = <&grf>;pinctrl-names = "default";pinctrl-0 = <&wifi_host_wake_irq>;/* 注意:如果排查发现Wi-Fi模块没有32.768K波形,且硬件上是由* RK PMU供给的,则打开下面的clock属性,按照实际使用的PMU型号填写,* 否在SDIO/Wi-Fi无法使用.** 海华AW-CM358SM使用的是外部晶振,无需打开clock属性。*///clocks = <&rk809 1>; //如果使用RK809,只能配置一个//clocks = <&hym8563>; //如果使用hym8563,只能配置一个//clock-names = "ext_clock";/* 按实际名字填写(但这里的名字我随便写的,听说海华和正基是兼容的,所以填了这个名字) */wifi_chip_type = "ap6256";/* 这里配置的是WIFI_HOST_WAKE_B引脚 */WIFI,host_wake_irq = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;status = "okay";
};&pinctrl {...wireless-wlan {wifi_host_wake_irq: wifi-host-wake-irq {/* 这里配置的是WIFI_HOST_WAKE_B引脚 */rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_down>;};};
};
其实实测发现,对于海华AW-CM358SM来说,不配置这个&wireless_wlan节点最终也会有wifi节点出来。
6.2、驱动移植
6.2.1、kernel menuconfig


6.2.2、传统驱动移植
- 进入内核驱动目录,将驱动文件复制进来:
cd <sdk>/kernel/drivers/net/wireless
cp nxp ./

- 修改Kconfig:
vi Kconfig
/* Kconfig */...config MXMWIFIEXtristate "NXP MxM WiFi Driver"depends on CFG80211helpThis driver is multi-chip-multi-interface driver(indicating Multi-Chip x Multi-Interface support) based onNXP 802.11n/ac chipsets. If you choose to build it as a module,it will be build 2 modules moal.ko and mlan.ko....

- 修改Makefile:
vi Makefile
/* Makefile */...obj-$(CONFIG_MXMWIFIEX) += nxp/...

- 修改defconfig:

- 在sdk根目录执行如下命令编译内核:
./build.sh kernel

至此,驱动已经编译完成。但是驱动的安装需要固件,可以自行通过文件系统overlay的方式将固件放到/lib/firmware/目录下。
6.2.3、RK SDK WIFI/BT驱动独立编译
RK SDK把wifibt的编译独立了出来,所以这里我们体验一下这种方法。注意!经过实测,要先按照上面将驱动移植进内核,才可以使用下面的独立编译。
- /external/rkwifibt/目录结构说明:

- firmware目录:包含各个厂家WiFiBT的firmware文件
- drivers目录:包含各个厂家的WiFiBT驱动
- bin目录:主要是原厂预置的一些二进制文件
- sh目录:主要是开机的WIFIBT的加载脚本,及测试脚本等
我们暂时只关注firmware和drivers目录。
- 进入drivers目录,创建aw-cm358sm文件夹,将驱动文件复制进来:
cd <sdk>/external/rkwifibt/drivers
mkdir aw-cm358sm
cd aw-cm358sm
cp nxp/* ./

- 进入firmware目录,创建azurewave文件夹。进入azureware目录,继续创建AW-CM358SM文件夹,将固件拷贝到该文件夹。
cd <sdk>/external/rkwifibt/firmware
mkdir azurewave
cd azurewave
mkdir AW-CM358SM
cd AW-CM358SM
cp xxxx ./

- 修改/device/rockchip/common/scripts/post-wifibt.sh
修改1:增加aw-cm358sm驱动的编译:

/* <sdk>/device/rockchip/common/scripts/post-wifibt.sh */...if [[ "$RK_WIFIBT_CHIP" = "AW-CM358SM" ]];thenecho "building aw-cm358sm driver"$KMAKE M=$RKWIFIBT_DIR/drivers/aw-cm358sm modulesfi...
修改2:将编译好的ko文件和固件拷贝到output目录,以备后面打包进rootfs。

/* <sdk>/device/rockchip/common/scripts/post-wifibt.sh */...if [[ "$RK_WIFIBT_CHIP" == "AW-CM358SM" ]];thenecho "Copy AW-CM358SM file to rootfs"cp $RKWIFIBT_DIR/firmware/azurewave/$RK_WIFIBT_CHIP/* \$TARGET_DIR/lib/firmware/cp $RKWIFIBT_DIR/drivers/aw-cm358sm/*.ko $TARGET_DIR/lib/modules/fi...
- 修改板级配置文件,添加
$RK_WIFIBT_CHIP环境变量:

- 在sdk根目录执行如下命令单独编译wifibt:
./build.sh wifibt

- 编译buildroot,更新rootfs。打包固件。
./build.sh buildroot && ./build.sh firmware
6.3、Wi-Fi 功能验证
6.3.1、加载驱动
- 查看未安装驱动前的ifconfig:

- 进入/lib/modules目录,按顺序安装驱动(该驱动有两个ko文件需要安装):

cd /lib/modules
insmod mlan.ko
insmod moal.ko
驱动加载成功:


6.3.2、STA模式测试
这里使用wpa_supplicant工具测试,需要在buildroot里提前安装。
WPA_SUPPLICANT是一个用于处理 Wi - Fi 连接认证和加密的守护进程(daemon)。它在 Linux、BSD 等操作系统中被广泛使用,用于实现客户端(如笔记本电脑、智能手机等设备)与 Wi - Fi 接入点(AP)之间的安全连接。
- 修改wpa_supplicant.conf配置文件,将ssid和psk替换成待连接的wifi名称和密码:
vi /etc/wpa_supplicant.conf

- 开启wpa_supplicant进程:
# 开启wpa_supplicant进程
# -c 后面接的是配置文件的路径
wpa_supplicant -B -i mlan0 -c /etc/wpa_supplicant.conf# 动态获取IP
dhcpcd mlan0

- ping测试:
ping -I mlan0 baidu.com

6.3.3、AP测试
海华awcm358sm有三个网络节点,其中uap0可用作AP节点:

这里使用hostapd工具测试,需要在buildroot里提前安装。
hostapd是一个用户空间的守护进程,主要用于将支持 Linux 的网络接口转换为一个 IEEE 802.11 无线接入点(AP)。简单来说,它可以让你的设备(如装有 Linux 系统的电脑或开发板)变成一个 Wi - Fi 热点,供其他无线设备连接。
板卡接入有线网络,确保可以上网:

hostapd需要一个配置文件,这里命名为hostapd-2.4g.conf,内容如下:
interface=uap0
driver=nl80211
channel=9
hw_mode=gauth_algs=1
ieee80211n=1
wpa=1ssid=OK3568_WIFI_2.4G_AP
wpa_passphrase=12345678
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
下面是AP模式的测试脚本hostapd.sh:
#!/bin/sh# kill wpa_supplicant
cnt=`ps aux | grep wpa_supplicant | grep -v grep | wc -l`
if [ "${cnt}" != "0" ];thenkillall wpa_supplicant > /dev/null
fi# kill hostapd
cnt1=`ps aux | grep hostapd | grep -v grep | wc -l`
if [ "${cnt1}" != "0" ];thenkillall hostapd > /dev/null
fi# stop dnsmasq
/etc/init.d/S80dnsmasq stop# start hostapd
hostapd /etc/hostapd-2.4g.conf &# enable device
sleep 1
ifconfig mlan0 up
ifconfig uap0 up
# 注意,这里的IP不要和eth0的IP在同一个网段
ifconfig uap0 192.168.5.1# start dnsmasq
/etc/init.d/S80dnsmasq start# 开启网络和IP转发
echo "1" > /proc/sys/net/ipv4/ip_forwardiptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
iptables -t nat -X
iptables -t mangle -Xiptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROPiptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
hostapd完成了AP热点的创建,现在为AP添加DHCP功能,这里使用dnsmasq工具。dnsmasq的配置文件在/etc/dnsmasq.conf,内容如下,主要规定了接口名和待分配的IP地址范围:
interface=uap0
bind-interfaces
except-interface=lo
dhcp-range=192.168.5.100,192.168.5.254,12h
dhcp-option=3,192.168.5.1
dhcp-option=6,192.168.5.1
一切准备就绪,开始测试,执行AP测试脚本hostapd.sh,需要执行两次:
sh hostapd.sh

手机查看热点:

查看路由表:
route -n

手机连接热点后,打印如下:

但目前是存在问题的,手机连接热点后上不了网。最初是内核没有开启iptables的支持,但后面开启之后,执行hostapd.sh测试脚本,内核直接崩溃,这个问题卡了挺久,暂时放弃了。
7、蓝牙适配
7.1、bt dts配置

配置uart8:
&uart8 {status = "okay";pinctrl-names = "default";pinctrl-0 = <&uart8m0_xfer &uart8m0_ctsn &uart8m0_rtsn>;
};
7.2、驱动移植
kernel menuconfig开启BT_HCIUART:

7.3、蓝牙功能验证
buildroot要添加bluez蓝牙工具软件包。
7.3.1、使能蓝牙设备
- 使能蓝牙设备:
# 还是要先加载wifi驱动
insmod /lib/modules/mlan.ko
insmod /lib/modules/moal.ko# 使能hci0
hciattach /dev/ttyS8 any -s 115200 115200 flow > /dev/null
hciconfig hci0 up

- 使本设备自身可被发现:
hciconfig hci0 piscan
- 查看蓝牙模块设备名称:
hciconfig hci0 name

- 手机查看蓝牙设备(苹果手机看不到):

7.3.2、扫描外设
hcitool scan

7.3.3、开发板发送文件给安卓手机
进入bluetooth终端:
/usr/libexec/bluetooth/bluetoothd -C -n &
bluetoothctl

打开蓝牙可连接可被发现属性:
discoverable on
扫描蓝牙设备(重新进入bluetooth终端后,需扫描设备才可以连接):
scan on

扫描到目标设备后,关闭扫描:
scan off
配对:
agent NoInputNoOutput
default-agent
pair A4:50:46:A5:9D:08

退出bluetooth终端:
quit
创建文件,用于待会的发送测试:
echo "send" > sendfile.txt
进入obexctl终端:
export $(dbus-launch)
/usr/libexec/bluetooth/obexd -r /tmp -a -n &
obexctl

连接手机:
connect A4:50:46:A5:9D:08

发送文件到手机:
send sendfile.txt

退出obexctl终端:
quit
相关文章:
RK356x bsp 5 - 海华AW-CM358SM Wi-Fi/Bt模组调试记录
文章目录 1、环境介绍2、目标3、海华AW-CM358SM3.1、基本信息3.2、支持SDIO3.03.3、电气特性 4、适配流程步骤5、SDIO控制器适配5.1、sdio dts配置5.2、验证 6、Wi-Fi 适配6.1、wifi dts配置6.2、驱动移植6.2.1、kernel menuconfig6.2.2、传统驱动移植6.2.3、RK SDK WIFI/BT驱动…...
支持Google Analytics快捷添加的CMS:费用与部署形式详解
CMS 的费用和部署形式是选择平台的重要参考因素,不同的业务需求需要不同的解决方案。本文将从费用和部署形式两个角度,详细分析支持 Google Analytics 快捷集成的 CMS 和工具,帮助您更好地了解这些平台的特点。 1. BigCommerce 费用ÿ…...
CSS | 实现三列布局(两边边定宽 中间自适应,自适应成比)
目录 示例1 (中间自适应 示例2(中间自适应 示例3(中间自适应 示例4 (自适应成比 示例5(左中定宽,右边自适应 示例6(中间自适应 示例7(中间自适应 示例8(中间定宽…...
fpga系列 HDL:跨时钟域同步 双触发器同步器
目录 **双触发器同步器(Two-Flip-Flop Synchronizer)示例代码**:双触发器同步器的优缺点优点:缺点:适用场景: 应用实例:同步来自spi_slave的单个使能信号 跨时钟域的设计需要特别小心࿰…...
金融项目实战 05|Python实现接口自动化——登录接口
目录 一、代码实现自动化理论及流程 二、脚本实现的理论和准备工作 1、抽取功能转为自动化用例 2、搭建环境(测试工具) 3、搭建目录结构 三、登录接口脚本实现 1、代码编写 1️⃣api目录 2️⃣script目录 2、断言 3、参数化 1️⃣编写数据存储文件:jso…...
《HTML在网络安全中的多面应用:从防范攻击到安全审查》
Html基础 Html简介 HTML(HyperText Markup Language,超文本标记语言)是用于描述网页内容和结构的标准语言。以下是对HTML的简要介绍: 基本概念 定义: HTML不是一种编程语言,而是一种标记语言。 它使用标…...
Linux网络 | 学习传输层网络协议之UDP(短篇)
前言: 本节内容正式迈入传输层网络协议的知识殿堂, 之前的文章, 我们都是在应用层进行翻来覆去。 比如http就是应用层协议, 只不过使用了tcp的系统调用。 从本节开始, 友友们将会学习传输层两大协议: UDP和…...
iOS - 内存屏障的使用场景
内存屏障的使用是为了解决以下几个关键问题: 1. CPU 乱序执行 // 没有内存屏障时,CPU 可能乱序执行 void example() {// 这两行代码可能被 CPU 重排序a 1; // 操作1flag true; // 操作2 }// 使用内存屏障确保顺序 void safeExample() {a 1;…...
MySQL 8.0 新特性详解与实用示例
MySQL 8.0 新特性详解与实用示例 1. 引言 MySQL 8.0 是 MySQL 版本系列中具有里程碑意义的更新版本,带来了大量新功能和优化,极大地提升了数据库的性能和可用性。本文将深入介绍 MySQL 8.0 的主要新特性及其应用场景,帮助你在项目中更高效地…...
【STM32-学习笔记-5-】ADC
文章目录 ADCADC函数Ⅰ、ADC_InitTypeDef结构体参数①、ADC_Mode②、ADC_DataAlign③、ADC_ExternalTrigConv④、ADC_ContinuousConvMode⑤、ADC_ScanConvMode⑥、ADC_NbrOfChannel Ⅱ、ADC配置示例1、单次转换,非扫描单次转换非扫描模式下,获取多通道的…...
TY1801 反激变换器PWM GaN功率开关
TY1801 是一款针对离线式反激变换器的多模式 PWM GaN 功率开关。TY1801 内置 GaN 功率管,它具备超宽 的 VCC 工作范围,非常适用于 PD 快充等要求宽输出电压的应用场合,系统不需要使用额外的绕组或外围降压电路,节省系统 BOM 成本。TY1801 支持 Burst&…...
Jenkins安装、插件下载及构建环境配置详解
Jenkins简介 1.1 简介 Jenkins 是一个基于Java开发的开源持续集成工具,它提供了一个开放且易用的软件平台,主要用于自动化构建、测试和部署软件项目,以实现持续集成(CI)和持续交付/部署(CD)。…...
ESP32,uart安装驱动uart_driver_install函数剖析,以及intr_alloc_flags 参数的意义
在 uart_driver_install 函数中,参数 RX_BUF_SIZE * 2 指定了接收缓冲区(RX buffer)的大小。这个参数对于 UART 驱动程序来说非常重要,因为它决定了可以存储多少接收到的数据,直到应用程序读取它们为止。下面是对该函数…...
Ubuntu把应用程序放到桌面
有时候我们下载的软件是一个文件夹,通常需要进入进入指定文件夹下去执行.sh 文件来启动,下面来个实例如何把idea放到桌面 打开文件目录/usr/share/applications/或者~/.local/share/applications/目录。第一个目录是全局的,所有用户都可以使…...
什么是端口映射
端口映射 端口映射(Port Mapping)是一种网络技术,用于将外部网络请求转发到内部网络的特定设备或服务。它通常用于以下场景: 外部访问内部服务:允许外部用户通过公网IP访问内网中的设备或服务。多设备共享IP…...
数据结构《MapSet哈希表》
文章目录 一、搜索树1.1 定义1.2 模拟实现搜索 二、Map2.1 定义2.2 Map.Entry2.3 TreeMap的使用2.4 Map的常用方法 三、Set3.1 定义3.2 TreeSet的使用3.3 Set的常用方法 四、哈希表4.1 哈希表的概念4.2 冲突4.2.1 冲突的概念4.2.2 冲突的避免1. 选择合适的哈希函数2. 负载因子调…...
【QT】QComboBox:activated信号和currentIndexChanged信号的区别
目录 1、activated1.1 原型1.2 触发机制1.3 使用场景1.4 连接信号和槽的方法1.4.1 方式一1.4.2 方式二 2、currentIndexChanged2.1 原型2.2 触发机制2.3 使用场景2.4 连接信号和槽的方法 1、activated 1.1 原型 [signal] void QComboBox::activated(int index) [signal] void…...
【Block总结】ELGCA模块,池化-转置(PT)注意力和深度卷积有效聚合局部和全局上下文信息
ELGCA结构 论文题目:ELGC-Net: Efficient Local-Global Context Aggregation for Remote Sensing Change Detection 论文链接:https://arxiv.org/pdf/2403.17909 官方github:https://github.com/techmn/elgcnet 高效局部-全局上下文聚合器&…...
MERN全栈脚手架(MongoDB、Express、React、Node)与Yeoman详解
MERN 全栈脚手架是一种用于快速构建基于 MongoDB、Express、React 和 Node.js 的全栈应用的框架或模板。它帮助开发者快速启动项目,减少了从零开始配置的时间。以下是关于 MERN 全栈脚手架的详细解析。 一、MERN 技术栈简介 MongoDB: 文档型数据库,用于…...
基于springboot+vue+微信小程序的宠物领养系统
基于springbootvue微信小程序的宠物领养系统 一、介绍 本项目利用SpringBoot、Vue和微信小程序技术,构建了一个宠物领养系统。 本系统的设计分为两个层面,分别为管理层面与用户层面,也就是管理者与用户,管理权限与用户权限是不…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
