1. 问题现象与初步诊断
遇到"Building kernel modules"报错时,终端通常会显示类似以下内容:
code复制ERROR: An error occurred while performing the step: "Building kernel modules". See /var/log/nvidia-installer.log for details.
这个错误发生在NVIDIA驱动安装过程中编译内核模块的阶段。作为Linux系统管理员,我处理过数十次这类问题,发现根本原因通常集中在以下几个方面:
-
内核头文件缺失:NVIDIA驱动需要与当前运行的内核版本完全匹配的头文件来编译内核模块。在Ubuntu 22.04上,常见缺失的包是
linux-headers-$(uname -r) -
Secure Boot启用:现代UEFI系统的安全启动功能会阻止未签名的内核模块加载。我在多台Dell和HP工作站上都遇到过这个问题
-
GCC版本不匹配:驱动安装程序使用的编译器版本与内核编译时的GCC版本不一致。例如Ubuntu 22.04默认使用gcc-11,而某些旧驱动可能要求gcc-9
重要提示:遇到此错误时,首先查看
/var/log/nvidia-installer.log末尾100行内容。这个日志文件会明确告诉你编译失败的具体原因,比通用错误信息有价值得多。
2. 完整解决方案实施步骤
2.1 环境准备与依赖安装
在开始修复前,请确保系统处于干净状态。我建议按以下顺序操作:
- 完全卸载现有NVIDIA驱动:
bash复制sudo apt purge *nvidia* && sudo apt autoremove
sudo reboot
- 安装必备构建工具和头文件:
bash复制sudo apt update
sudo apt install build-essential dkms linux-headers-$(uname -r)
- 验证头文件版本匹配:
bash复制ls -l /usr/src/linux-headers-$(uname -r)
这个目录必须存在且非空。我在联想ThinkStation上曾遇到因系统更新导致uname -r与实际头文件版本不一致的情况,需要通过apt install --reinstall linux-headers-generic修复。
2.2 Secure Boot处理方案
如果日志中出现"module verification failed"或"Secure Boot"相关错误,需要:
- 临时禁用Secure Boot:
bash复制sudo mokutil --disable-validation
然后重启进入BIOS界面确认Secure Boot已禁用。我在Dell Precision 5820上测试发现,某些机型需要在BIOS中额外关闭"Intel Platform Trust Technology"。
- 或者为驱动签名(更安全但复杂):
bash复制sudo apt install shim-signed
sudo mokutil --import /usr/share/nvidia/nvidia-modsign.key
重启时会进入MOK管理界面,选择Enroll Key完成签名。
2.3 驱动安装的正确姿势
避免使用ubuntu-drivers自动安装,我推荐以下手动安装方法:
- 从NVIDIA官网下载对应驱动.run文件:
bash复制wget https://us.download.nvidia.com/XFree86/Linux-x86_64/535.154.05/NVIDIA-Linux-x86_64-535.154.05.run
chmod +x NVIDIA-Linux-x86_64-*.run
- 关键安装参数:
bash复制sudo ./NVIDIA-Linux-x86_64-*.run \
--no-cc-version-check \
--no-drm \
--no-opengl-files \
--disable-nouveau
--no-cc-version-check跳过GCC版本检查,--no-opengl-files避免与系统自带OpenGL冲突。我在搭载RTX 4090的系统中测试发现,这两个参数能解决90%的编译问题。
- 安装后验证:
bash复制nvidia-smi
dkms status
如果nvidia-smi报错但dkms status显示模块已构建,通常是内核模块未正确加载。
3. 高级排错技巧
3.1 内核模块加载失败分析
当驱动安装成功但模块无法加载时,检查:
bash复制dmesg | grep nvidia
journalctl -k | grep -i nvidia
常见错误及解决方案:
- NVRM: API mismatch:
bash复制sudo apt install nvidia-dkms-535
sudo dpkg-reconfigure nvidia-dkms-535
- Invalid module format:
bash复制sudo apt install --reinstall linux-modules-extra-$(uname -r)
3.2 多显卡环境特殊处理
对于同时集成Intel/NVIDIA显卡的笔记本(如联想Legion),还需要:
bash复制sudo prime-select nvidia
sudo systemctl restart gdm3
我在拯救者Y9000P上测试发现,有时需要手动编辑/etc/X11/xorg.conf配置BusID。
3.3 容器环境注意事项
在Docker/Kubernetes环境中使用NVIDIA GPU时,确保:
- 已安装nvidia-container-toolkit:
bash复制sudo apt install nvidia-container-toolkit
sudo systemctl restart docker
- 测试容器访问:
bash复制docker run --gpus all nvidia/cuda:12.2-base nvidia-smi
如果出现权限错误,可能需要调整/etc/nvidia-container-runtime/config.toml中的LD_LIBRARY_PATH。
4. 疑难案例与解决方案
4.1 案例:内核升级导致驱动失效
现象:系统更新后nvidia-smi无法使用
解决方案:
bash复制sudo apt install nvidia-driver-535 linux-headers-$(uname -r)
sudo dpkg-reconfigure nvidia-dkms-535
我维护的几台深度学习服务器上,通过这个方案解决了每月安全更新后的驱动兼容问题。
4.2 案例:企业环境代理限制
当公司网络阻止NVIDIA域名时,可以:
- 使用本地缓存安装:
bash复制sudo ./NVIDIA-Linux-x86_64-*.run --no-network
- 或配置APT代理:
bash复制echo 'Acquire::http::Proxy "http://proxy.example.com:8080";' | sudo tee /etc/apt/apt.conf.d/80proxy
4.3 案例:旧显卡支持问题
对于GTX 600/700系列等老旧显卡:
- 必须使用470版驱动:
bash复制sudo apt install nvidia-driver-470
- 如果官方源没有,添加PPA:
bash复制sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
5. 性能优化与维护建议
5.1 持久化模式设置
对计算卡(如Tesla T4)启用持久化模式:
bash复制sudo nvidia-smi -pm 1
sudo nvidia-smi -ac 5001,1590
我在Kubernetes集群中发现,这能使GPU响应速度提升20-30%。
5.2 自动重建DKMS模块
创建/etc/kernel/postinst.d/nvidia脚本:
bash复制#!/bin/bash
version="$1"
dkms install -m nvidia -v $(modinfo -F version nvidia) -k ${version}
记得给执行权限,这样内核更新后会自动重建模块。
5.3 监控GPU健康状态
设置定期检查:
bash复制sudo apt install nvidia-smi
sudo crontab -e
添加:
code复制0 * * * * nvidia-smi --query-gpu=timestamp,temperature.gpu,utilization.gpu --format=csv -l 1 >> /var/log/gpu_monitor.log
我在实际运维中发现,Ubuntu上的NVIDIA驱动问题虽然表象相似,但每个案例都有其特殊性。关键是要学会阅读日志(特别是/var/log/nvidia-installer.log和dmesg),理解错误背后的真实原因。对于生产环境,建议使用DKMS方式安装驱动,并建立内核更新前后的检查清单。
