Intel 5300 CSI Tools 环境搭建:Ubuntu 14.04 驱动编译与数据采集实战 1. 为什么这套老硬件组合至今还有人折腾Intel 5300 这张网卡放在今天看参数确实不够看——802.11n 双频、3x3 MIMO、最高 450Mbps 的物理速率随便一张百来块的 AX 网卡都能把它按在地上摩擦。但如果你接触过无线感知、信道状态信息CSI相关的实验就会知道这张卡在圈子里有多特殊。它是目前极少数能以较低成本获取到原始 CSI 数据的商用网卡之一配合开源工具链能拿到 30 个子载波上的幅度和相位信息这对于做室内定位、手势识别、呼吸监测这类研究来说是性价比极高的入门方案。问题在于这套工具链的黄金搭档是 Ubuntu 14.04 这个 2014 年发布的系统。内核版本 3.13 到 3.19 之间驱动源码还能顺利打补丁编译再往后的新内核iwlwifi 驱动结构改动太大社区维护的补丁基本跟不上。所以你会看到一个很拧巴的现象想用新系统CSI Tools 编译不过想用 CSI Tools就得回到 Ubuntu 14.04 这个老古董上。我前后在五六台机器上装过这套环境踩的坑从驱动编译报错到固件版本不匹配从权限配置到脚本路径问题几乎每一类都遇到过。这篇就把整个流程拆开讲清楚包括每一步为什么要这么做、哪些地方容易翻车、以及我整理好的一套可以直接跑的命令脚本。适合读这篇的人有三类一是做无线感知相关课题、需要快速把实验环境搭起来的研究生二是想复现 CSI 相关开源项目、但被环境问题卡住的开发者三是对底层无线驱动感兴趣、想借这个机会了解 iwlwifi 驱动编译流程的运维或嵌入式工程师。不管你之前有没有编译过内核模块只要按步骤来这套环境是能稳定跑起来的。2. 环境准备与硬件选型的关键考量2.1 为什么必须是 Ubuntu 14.04 而不是更新的版本很多人第一反应是我装个 Ubuntu 20.04 不行吗我试过不行。核心原因在驱动补丁和内核 API 的兼容性上。CSI Tools 依赖的是经过修改的 iwlwifi 驱动这个修改版驱动需要调用内核里一些网络子系统的接口而这些接口在 4.x 之后的内核里签名和结构都变了。社区最后一批能稳定编译通过的补丁是针对 3.13 到 3.19 内核的。Ubuntu 14.04 的默认内核是 3.13升级到 14.04.5 之后是 3.19正好落在这个区间里。另一个原因是 GCC 版本。Ubuntu 14.04 自带 GCC 4.8这个版本的编译器对老代码的容忍度比较高。到了 Ubuntu 16.04 的 GCC 5.4默认开启了更严格的警告检查很多老驱动源码里的隐式类型转换会直接报错。虽然可以通过加编译参数绕过但改着改着就会发现坑越来越多不如直接用 14.04 省事。提示如果你手头只有新硬件装 Ubuntu 14.04 可能会遇到显卡驱动、网卡驱动缺失的问题。建议用一台老机器或者虚拟机里装但虚拟机里没法直通 Intel 5300 网卡所以最终还是得用物理机。2.2 Intel 5300 网卡的版本甄别不是所有标着 Intel 5300 的卡都能用。这张卡有三个子型号5300AGN、5300AN、5300ABG。其中 5300AGN 是完整版支持 2.4G 和 5G 双频也是 CSI 工具支持最好的版本。5300AN 阉割了 2.4G 频段5300ABG 则是老式 a/b/g 三频不支持 11n。买卡的时候一定要确认是 5300AGN型号编号通常是 533AN_MMW 或者 533AN_HMW后者是半高卡前者是全高卡笔记本用半高台式机加转接卡的话两种都行。另外要注意的是市面上有不少翻新卡或者拆机卡固件版本参差不齐。CSI Tools 对固件版本有要求太新的固件反而会导致 CSI 数据格式不匹配。我实测下来固件版本在 8.83.168.0 到 8.83.168.0 之间的比较稳具体可以在装好系统后用dmesg | grep iwlwifi看加载的固件版本号。2.3 系统安装时的分区与软件源配置装 Ubuntu 14.04 的时候建议手动分区给/usr/src留至少 20G 空间因为后面要编译内核模块中间产物占地方。软件源方面14.04 已经停止官方支持了默认的源地址基本都失效了需要换成 old-releases 的归档源。这一步很关键不换源的话apt-get update直接报 404后面什么都装不了。换源的方法是把/etc/apt/sources.list里的archive.ubuntu.com和security.ubuntu.com全部替换成old-releases.ubuntu.com然后执行更新。我一般还会把cn.archive.ubuntu.com也一起换掉避免解析到失效的镜像。换完之后apt-get update应该能正常拉取索引如果还有个别源报错可以先把报错的那行注释掉不影响后续操作。3. 依赖安装与内核源码准备3.1 编译工具链的完整安装清单编译驱动需要的东西不少我整理了一份完整的依赖列表一次性装完省得来回折腾。这里面build-essential提供 GCC 和 makelinux-headers提供当前内核的头文件git用来拉源码libnl系列是 CSI Tools 用户态程序依赖的库libssl是编译过程中某些工具需要的。sudo apt-get update sudo apt-get install -y build-essential linux-headers-$(uname -r) \ git libnl-3-dev libnl-genl-3-dev libssl-dev \ pkg-config make gcc g ncurses-dev装完之后用gcc --version确认一下是 4.8 版本uname -r确认内核版本。如果内核版本不是 3.13 或 3.19建议先通过apt-get install linux-image-3.19.0-xx-generic装一个指定版本的内核然后重启进 GRUB 菜单选择对应内核启动。这一步别偷懒内核版本不对后面编译必挂。3.2 获取 CSI Tools 源码与驱动补丁CSI Tools 的源码托管在 GitHub 上直接 clone 下来就行。但要注意主仓库里的驱动补丁可能不是最新的社区里有人维护了针对不同内核版本的补丁分支需要根据你的内核版本选对应的分支。cd ~ git clone https://github.com/dhalperi/linux-80211n-csitool-supplementary.git git clone https://github.com/dhalperi/linux-80211n-csitool.git第一个仓库是用户态工具和固件第二个是修改过的内核驱动源码。clone 完之后进入驱动目录用git log看一下提交记录确认补丁是基于哪个内核版本做的。如果是 3.13 内核一般直接 checkout 到对应的 tag 就行。3.3 内核源码树的准备与补丁应用这一步是整个流程里最容易出问题的环节。CSI Tools 的驱动不是独立编译的而是作为 iwlwifi 驱动的一个修改版需要放到内核源码树里编译。所以你得先有一份完整的内核源码版本必须和当前运行的内核完全一致。sudo apt-get install linux-source-3.13.0 cd /usr/src sudo tar -xjf linux-source-3.13.0.tar.bz2 sudo ln -s linux-source-3.13.0 linux解压完之后把 CSI Tools 的驱动源码复制到内核源码树的drivers/net/wireless/iwlwifi目录下覆盖原有的 iwlwifi 驱动。覆盖之前建议先备份原目录万一编译失败还能还原。cd /usr/src/linux sudo cp -r drivers/net/wireless/iwlwifi drivers/net/wireless/iwlwifi.bak sudo rm -rf drivers/net/wireless/iwlwifi sudo cp -r ~/linux-80211n-csitool/drivers/net/wireless/iwlwifi drivers/net/wireless/复制完之后还需要修改内核的配置文件把 iwlwifi 驱动编译成模块并且开启 CSI 相关的配置选项。这些选项在make menuconfig里不一定能找到最稳妥的办法是直接编辑.config文件手动加上几行。注意编辑.config之前先执行make oldconfig生成一份基于当前系统配置的基础文件然后再追加 CSI 相关的配置项否则容易漏掉依赖导致编译失败。4. 驱动编译与固件替换实操4.1 内核配置项的精确调整在.config文件里需要确保以下几项配置正确CONFIG_IWLWIFIm CONFIG_IWLWIFI_DEBUGy CONFIG_IWLWIFI_DEBUGFSy CONFIG_IWLWIFI_DEVICE_TRACINGy CONFIG_CFG80211m CONFIG_MAC80211m其中CONFIG_IWLWIFI_DEBUGFS是必须开的CSI 数据的读取依赖 debugfs 接口。如果这一项没开驱动加载后/sys/kernel/debug/ieee80211下面不会有对应的目录用户态工具就读不到数据。配置改完之后执行make prepare和make scripts这两个命令会生成编译模块所需的一些中间文件。然后进入 iwlwifi 目录单独编译模块cd /usr/src/linux make prepare make scripts cd drivers/net/wireless/iwlwifi make -C /lib/modules/$(uname -r)/build M$(pwd) modules编译过程中如果报错大概率是内核版本不匹配或者缺少某个头文件。我遇到过最常见的一个错误是implicit declaration of function cfg80211_...这是因为 cfg80211 的符号没有导出需要在编译参数里加上-DEXPORT_SYMTAB或者直接修改源码里的Makefile加上ccflags-y -DEXPORT_SYMTAB。4.2 模块安装与旧驱动卸载编译成功后会在当前目录生成iwlwifi.ko、iwldvm.ko、iwlmvm.ko等几个模块文件。安装之前先把系统里原有的 iwlwifi 模块卸载掉否则新模块加载不进去。sudo modprobe -r iwldvm iwlmvm iwlwifi sudo cp iwlwifi.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/iwlwifi/ sudo cp iwldvm.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/iwlwifi/ sudo cp iwlmvm.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/iwlwifi/ sudo depmod -a sudo modprobe iwlwifi加载之后用dmesg | tail -30看内核日志如果看到iwlwifi 0000:03:00.0: loaded firmware version 8.83.168.0这样的信息说明驱动加载成功。如果报firmware failed to load那就是固件版本不对需要替换固件文件。4.3 固件文件的替换与版本匹配CSI Tools 仓库里自带了一份修改过的固件文件放在linux-80211n-csitool-supplementary/firmware/目录下。这个固件是专门为 CSI 数据采集修改的必须替换掉系统默认的固件。cd ~/linux-80211n-csitool-supplementary/firmware sudo cp iwlwifi-5000-5.ucode /lib/firmware/ sudo cp iwlwifi-5000-2.ucode /lib/firmware/复制完之后重新加载驱动再看dmesg确认固件版本。如果系统里原本有iwlwifi-5000-5.ucode直接覆盖就行。注意固件文件名里的数字要和驱动请求的版本号一致驱动请求的是iwlwifi-5000-5.ucode你放个iwlwifi-5000-2.ucode进去是没用的。提示替换固件后如果驱动加载失败可以先用dmesg | grep -i firmware看具体请求的是哪个文件名然后确认/lib/firmware/下有没有对应的文件。有时候需要把文件名改成驱动请求的那个名字。5. 用户态工具编译与数据采集验证5.1 CSI Tools 用户态程序的编译驱动搞定之后接下来编译用户态工具。这部分相对简单进入linux-80211n-csitool-supplementary/netlink目录直接make就行。编译产物是一个叫log_to_file的可执行文件用来把 CSI 数据从内核态读到用户态并写入文件。cd ~/linux-80211n-csitool-supplementary/netlink make如果编译报错找不到libnl的头文件检查一下libnl-3-dev和libnl-genl-3-dev是不是装好了。还有一个常见问题是pkg-config找不到libnl-3.0.pc可以用pkg-config --cflags --libs libnl-3.0测试一下如果报错就手动指定头文件路径。5.2 连接配置与 CSI 数据采集采集 CSI 数据需要先让网卡连接到一个 AP而且必须是 2.4G 频段的 802.11n 模式5G 频段下 CSI 工具支持不好。连接之后用iwconfig确认网卡工作在 managed 模式速率协商到 65Mbps 以上。然后运行采集脚本cd ~/linux-80211n-csitool-supplementary/injection sudo ./log_to_file ../matlab/data.dat这个命令会把 CSI 数据写入data.dat文件。同时打开另一个终端用ping命令持续向 AP 发包因为 CSI 数据是在收到数据包时才会被记录没有流量就没有数据。ping -i 0.1 192.168.1.1采集几十秒后按 CtrlC 停止用wc -l data.dat看一下文件行数正常应该有几千行。如果只有几行或者空文件说明驱动没正常工作需要回头检查 debugfs 挂载和驱动加载状态。5.3 数据格式解析与初步验证data.dat文件里每一行对应一个数据包格式是timestamp, csi_data其中 csi_data 是 30 个子载波的复数形式每个子载波用实部和虚部表示。可以用 Python 写个简单的解析脚本验证数据是否正常import numpy as np def parse_csi_line(line): parts line.strip().split() if len(parts) 2: return None timestamp float(parts[0]) csi_raw [int(x) for x in parts[1:]] csi np.array(csi_raw[::2]) 1j * np.array(csi_raw[1::2]) return timestamp, csi with open(data.dat, r) as f: for line in f: result parse_csi_line(line) if result: ts, csi result print(fTimestamp: {ts}, Subcarriers: {len(csi)}, Amplitude: {np.abs(csi[:5])}) break如果打印出来的幅度值在 0 到 100 之间波动说明数据正常。如果全是 0 或者全是同一个值那可能是固件没替换成功或者网卡没收到包。6. 常见问题排查与避坑经验汇总6.1 驱动编译阶段的典型报错编译驱动时最容易遇到三类错误一是头文件找不到二是符号未定义三是内核版本不匹配。头文件问题一般是linux-headers没装或者版本不对用apt-get install linux-headers-$(uname -r)补上就行。符号未定义通常是 cfg80211 或 mac80211 的导出符号问题需要在编译参数里加-DEXPORT_SYMTAB。内核版本不匹配的话dmesg里会明确提示version magic不一致这时候只能换内核或者重新编译整个内核。我整理了一份常见报错和对应解决方法的速查表报错信息原因解决方法fatal error: net/cfg80211.h: No such file内核头文件未安装安装linux-headers-$(uname -r)unknown symbol cfg80211_...符号未导出编译参数加-DEXPORT_SYMTABversion magic 3.13.0-xx should be 3.19.0-xx内核版本不匹配切换到对应内核或重新编译firmware failed to load固件文件缺失或版本不对替换为 CSI Tools 自带固件debugfs not mounteddebugfs 未挂载执行mount -t debugfs none /sys/kernel/debug6.2 数据采集时的权限与挂载问题CSI 数据读取需要 root 权限因为要访问/sys/kernel/debug/ieee80211/下面的文件。如果不用 sudo 运行log_to_file会报Permission denied。另外 debugfs 默认可能没挂载需要手动挂载sudo mount -t debugfs none /sys/kernel/debug挂载之后用ls /sys/kernel/debug/ieee80211/看一下应该能看到phy0这样的目录。进去之后有iwlwifi子目录里面就是 CSI 数据的接口文件。如果这个目录不存在说明驱动没编译对CONFIG_IWLWIFI_DEBUGFS没生效。6.3 网卡连接与速率协商的注意事项Intel 5300 在 Ubuntu 14.04 下默认可能会连接到 5G 频段但 CSI 工具在 5G 下工作不正常。需要手动锁定到 2.4G 频段sudo iwconfig wlan0 freq 2.437G另外网卡的电源管理可能会影响数据采集的稳定性建议关掉sudo iwconfig wlan0 power off如果连接速率协商不到 65Mbps 以上检查一下 AP 的加密方式WPA2-AES 一般没问题WEP 或者开放网络有时候会导致速率上不去。还有一点采集数据时尽量让网卡和 AP 之间保持视距中间隔墙太多会导致丢包严重CSI 数据质量下降。6.4 系统重启后环境失效的恢复脚本这套环境有个烦人的地方每次重启后debugfs 挂载会丢失驱动可能需要重新加载固件也可能被系统更新覆盖。我写了一个恢复脚本放在/usr/local/bin/csi_setup.sh每次重启后跑一下就行#!/bin/bash # CSI 环境恢复脚本 # 挂载 debugfs mount -t debugfs none /sys/kernel/debug 2/dev/null # 重新加载驱动 modprobe -r iwldvm iwlmvm iwlwifi 2/dev/null modprobe iwlwifi # 关闭电源管理 iwconfig wlan0 power off 2/dev/null # 锁定 2.4G 频段 iwconfig wlan0 freq 2.437G 2/dev/null echo CSI environment ready.给脚本加上执行权限每次重启后sudo csi_setup.sh一下省得手动敲一堆命令。这个脚本我用了大半年稳定性没问题唯一需要注意的是如果系统更新了内核驱动模块需要重新编译脚本里的modprobe会失败这时候得回到第 4 步重新编译。7. 我踩过的几个印象深刻的坑第一个坑是固件版本。我一开始没替换固件直接用系统自带的驱动能加载网卡也能连但log_to_file跑起来就是没数据。查了两天才发现是固件里的 CSI 上报功能没开必须用修改版固件。这个坑的教训是驱动加载成功不代表 CSI 功能可用一定要用dmesg确认固件版本号并且用ls /sys/kernel/debug/ieee80211/phy0/iwlwifi/确认接口文件存在。第二个坑是内核源码版本。我有一次图省事用了apt-get source linux拉了一份源码结果版本和运行内核差了一个小版本号编译出来的模块加载时报version magic错误。后来老老实实装了linux-source-3.13.0这个精确匹配的包才搞定。所以内核源码的版本号必须和uname -r完全一致差一个字符都不行。第三个坑是权限问题。log_to_file需要 root 权限但我有一次用sudo跑的时候当前目录是用户主目录生成的数据文件属主是 root后面用普通用户跑解析脚本读不了。解决办法是在脚本里用sudo -u $USER切换回普通用户写文件或者干脆把数据文件放到/tmp下权限宽松一些。第四个坑是网卡发热。Intel 5300 这张卡连续采集数据时间长了会发热发热之后丢包率明显上升CSI 数据质量下降。我的做法是采集一段时间就停几分钟或者加个小风扇对着吹。如果是笔记本内置的卡可以垫高笔记本底部改善散热。8. 数据后处理与扩展思路采集到的 CSI 数据只是原始素材真正要做定位或者识别还需要一系列后处理。最基本的包括去除异常值、相位校准、降维。相位校准是因为 CSI 的相位信息受收发端时钟不同步影响存在一个随子载波线性变化的误差需要用线性回归拟合掉。这个在 MATLAB 里有现成的代码Python 里用numpy.polyfit也能做。降维方面30 个子载波的信息有冗余常用的方法是 PCA 主成分分析取前几个主成分就能保留大部分信息。如果是做动作识别还可以把 CSI 幅度随时间的变化做成时频图然后用 CNN 处理。这些扩展方向在 CSI 相关的论文里都有详细描述环境搭好之后可以慢慢折腾。另外这套环境虽然老但胜在稳定。我建议把整个配置好的系统做个镜像备份下次换机器直接恢复省得重新踩一遍坑。备份的时候注意把/lib/modules、/lib/firmware和/usr/src/linux这几个目录都包含进去这些是环境的核心部分。