背景
在 Linux 系统中,有些硬件驱动并不完全依赖发行版内核自带模块,而是需要额外使用第三方源码、DKMS 或手动安装脚本进行维护。常见场景包括无线网卡、特殊声卡、旧硬件驱动、笔记本专用补丁模块等。
这类源码最初往往会被临时 clone 到用户目录,例如:
~/workspace/some-driver
这种做法在测试阶段很方便,但如果这个驱动后来成为系统长期运行所依赖的一部分,继续放在临时工作目录里就不太合适了。
一次 MacBook 声卡驱动维护过程中,就遇到了这个问题:驱动源码原本放在用户的 workspace 目录中,但该驱动实际上已经成为系统升级内核后恢复声音的重要维护组件。因此,有必要把源码移动到更合适的长期位置。
用户工作目录不适合长期保存系统驱动源码
类似下面的位置更适合作为临时工作区:
~/workspace/
~/Downloads/
~/tmp/
这些目录的特点是:
适合临时测试
适合下载和编译
适合短期修改
适合随时清理
但如果里面存放的是长期依赖的系统驱动源码,就会出现几个问题:
容易被误删
容易和普通项目混在一起
不利于系统维护脚本引用
不适合被 root 执行的 hook 长期依赖
目录语义不清晰
尤其是 DKMS 驱动源码,它虽然最初只是一个 git 仓库,但后续可能会被反复用于:
git pull 更新源码
重新安装 DKMS 模块
内核升级后手动恢复驱动
pacman hook 自动重建模块
这种性质已经不再是普通用户项目,而是本机系统维护资源。
推荐位置:/usr/local/src
对于本机管理员手动维护、非发行版包管理器安装的源码,一个比较合理的位置是:
/usr/local/src/
例如:
/usr/local/src/snd_hda_macbookpro
这个位置的语义比较清楚:
/usr/local
本机管理员手动安装或维护的内容
/usr/local/src
本机管理员手动保留的源码
它不同于发行版包管理器主要管理的 /usr/bin、/usr/lib、/usr/share 等路径,也不同于用户自己的普通文档目录。
因此,把第三方驱动的上游源码仓库放在 /usr/local/src,可以理解为:
这是本机长期维护用源码
不是普通用户项目
不是临时下载文件
不是 DKMS 自动生成目录
也不是 pacman 软件包内容
需要区分的三个目录
以一个 DKMS 声卡驱动为例,整理后的结构可以分为三层。
1. 上游源码仓库
/usr/local/src/snd_hda_macbookpro
这是手动保留的 git 仓库,用于以后更新源码和重新安装驱动。
它的用途包括:
git pull --ff-only
./install.cirrus.driver.sh -i
./install.cirrus.driver.sh -r
这个目录是人为维护的,不是 DKMS 自动生成的。
2. DKMS 注册源码目录
/usr/src/snd_hda_macbookpro-0.1
这是 DKMS 实际注册和构建时使用的源码目录。安装脚本或 DKMS 会把源码放到这里。
这个路径属于系统级内核模块构建体系,不建议随便移动或手动清理,除非明确知道自己在重新注册 DKMS 模块。
3. DKMS 构建状态目录
/var/lib/dkms/snd_hda_macbookpro/0.1
这是 DKMS 的构建记录、状态和不同内核版本安装信息所在的位置。
例如执行:
dkms status
看到的模块状态,就与这里的记录有关。
为什么不直接只依赖 /usr/src
有人可能会问:既然 DKMS 已经把源码放进 /usr/src,是否还需要保留 /usr/local/src 下的 git 仓库?
答案是:最好保留。
原因是 /usr/src/snd_hda_macbookpro-0.1 更像是 DKMS 当前注册使用的源码副本,不一定适合作为长期更新和维护上游项目的 git 仓库。
而 /usr/local/src/snd_hda_macbookpro 的作用是:
保留上游 git 历史
方便 git pull
方便重新运行安装脚本
方便在 DKMS 状态损坏时重新注册
方便作为 pacman hook 或维护脚本的稳定来源
也就是说:
/usr/local/src
人维护的上游源码
/usr/src
DKMS 使用的注册源码
/var/lib/dkms
DKMS 的构建状态
这三个目录用途不同,不应混为一谈。
实际移动方式
假设源码原本位于:
~/workspace/snd_hda_macbookpro
可以移动到:
/usr/local/src/snd_hda_macbookpro
操作命令如下:
OLD="$HOME/workspace/snd_hda_macbookpro"
NEW="/usr/local/src/snd_hda_macbookpro"
test -d "$OLD" || { echo "旧目录不存在: $OLD"; exit 1; }
test ! -e "$NEW" || { echo "目标目录已存在: $NEW"; exit 1; }
sudo mkdir -p /usr/local/src
sudo mv "$OLD" "$NEW"
sudo chown -R root:root "$NEW"
sudo git -C "$NEW" status --short
sudo git -C "$NEW" remote -v
ls -ld "$NEW"
移动完成后,如果 git status --short 显示本地有修改,例如:
M dkms.conf
?? dkms.conf.orig
通常表示安装脚本曾经修改或备份过配置文件。为了让 /usr/local/src 下的仓库保持干净,可以重置为上游状态:
NEW="/usr/local/src/snd_hda_macbookpro"
sudo git -C "$NEW" reset --hard HEAD
sudo rm -f "$NEW/dkms.conf.orig"
sudo git -C "$NEW" status --short
sudo git -C "$NEW" remote -v
ls -ld "$NEW"
如果 status --short 没有输出,就说明仓库已经恢复为干净状态。
移动源码会不会影响当前驱动
一般不会。
因为当前已经安装好的 DKMS 模块主要依赖:
/usr/src/snd_hda_macbookpro-0.1
/var/lib/dkms/snd_hda_macbookpro/0.1
而不是原来的 clone 目录。
换句话说,移动 /home/.../workspace/snd_hda_macbookpro 到 /usr/local/src/snd_hda_macbookpro,不会直接改变当前已经加载的内核模块。
真正需要更新的是以后手动维护时使用的路径。
原来可能是:
cd ~/workspace/snd_hda_macbookpro
移动后应改为:
cd /usr/local/src/snd_hda_macbookpro
后续维护命令
以后内核升级后,如果需要重新安装或恢复该 DKMS 驱动,可以使用:
cd /usr/local/src/snd_hda_macbookpro
sudo git pull --ff-only
sudo ./install.cirrus.driver.sh -r || true
sudo ./install.cirrus.driver.sh -i
sudo depmod -a
reboot
重启后检查:
dkms status
modinfo -n snd-hda-codec-cs8409
aplay -l
对于 DKMS 覆盖内核自带模块的场景,尤其要确认模块路径是否位于:
/lib/modules/当前内核版本/updates/dkms/
如果仍然位于:
/lib/modules/当前内核版本/kernel/
就说明系统可能仍在使用内核自带原始模块,而不是 DKMS 修正版模块。
是否适合放在用户目录
如果只是临时测试,放在用户目录没有问题。例如:
~/workspace/
~/src/
~/Projects/
但如果这个源码已经成为系统维护的一部分,尤其是会被 root 权限脚本、DKMS、pacman hook 或内核升级恢复流程引用,那么放在 /usr/local/src 更合理。
可以简单按下面的原则判断:
临时编译、临时测试、普通项目
放用户目录
长期维护、本机依赖、系统驱动、root 脚本会引用
放 /usr/local/src
DKMS 自动注册源码
放 /usr/src
DKMS 构建状态
放 /var/lib/dkms
总结
手动维护的 Linux 驱动源码不一定适合长期放在用户的 workspace 目录中。对于已经成为系统运行依赖的第三方驱动源码,放在 /usr/local/src 更清晰、更稳定,也更符合目录语义。
整理后的结构可以概括为:
/usr/local/src/snd_hda_macbookpro
上游源码仓库,长期保留,用于 git pull 和重新安装
/usr/src/snd_hda_macbookpro-0.1
DKMS 当前注册使用的源码
/var/lib/dkms/snd_hda_macbookpro/0.1
DKMS 构建状态与模块安装记录
这样的结构比把系统驱动源码长期放在用户 workspace 中更干净,也更适合后续内核升级、DKMS 重建和系统维护。