4. 驱动日志配置与错误排查
任务说明
本案例面向NPU驱动加载失败场景:系统启动或驱动插入时,insmod/modprobe返回错误,但默认日志级别下看不到有效线索。目标是通过配置驱动日志级别,捕获完整错误信息,并依据日志定位根因(如固件缺失、地址冲突、电源时序等)。完成本案例后,你将掌握驱动日志系统的控制方法,并具备独立排查加载失败的基本路径。
驱动日志框架与级别说明
NPU驱动通常基于Linux内核日志框架。日志级别由低到高为:DEBUG(7)、INFO(6)、NOTICE(5)、WARNING(4)、ERROR(3)。驱动加载失败的关键信息多出现在INFO至ERROR区间,而定位根因往往需要DEBUG级信息(如寄存器读写序列、固件加载路径)。内核默认console_loglevel通常为4(仅显示WARNING及以上),导致INFO级加载流程和DEBUG级细节被丢弃。
日志级别配置方法
本案例提供两种配置路径:运行时通过procfs调整内核日志阈值,以及编译期通过驱动模块参数启用调试输出。前者适用于现场快速排查,后者适用于需要持久化调试的场景。以下实现聚焦运行时配置,因为它无需重新编译驱动,可直接作用于当前故障环境。
实现:日志级别控制脚本
创建一个Shell脚本npu_log_config.sh,用于查看和调整NPU驱动相关日志级别,并在加载失败时自动捕获完整日志到文件:
#!/bin/bash
# 文件: npu_log_config.sh
# 功能: 配置NPU驱动日志级别并捕获加载错误日志
# 用法: ./npu_log_config.sh [debug|info|warn|error]
# 日志保存路径
LOG_FILE="/var/log/npu_driver_load.log"
# 获取当前控制台日志级别
get_console_level() {
cat /proc/sys/kernel/printk | awk '{print $1}'
}
# 设置控制台日志级别
# 参数: 级别数字 (7=debug, 6=info, 4=warn, 3=error)
set_console_level() {
local level=$1
# 同时设置控制台和默认日志级别
echo "$level $level" > /proc/sys/kernel/printk 2>/dev/null
if [ $? -eq 0 ]; then
echo "[OK] 控制台日志级别已设置为: $level"
else
echo "[FAIL] 设置失败,请以root权限运行"
exit 1
fi
}
# 根据参数映射日志级别
map_level() {
case "$1" in
debug) echo 7 ;;
info) echo 6 ;;
warn) echo 4 ;;
error) echo 3 ;;
*) echo "无效级别: $1 (可选: debug/info/warn/error)"; exit 1 ;;
esac
}
# 主流程
echo "=== NPU驱动日志配置工具 ==="
echo "当前控制台日志级别: $(get_console_level) (7=debug, 6=info, 4=warn, 3=error)"
# 如果提供了级别参数,则进行设置
if [ $# -eq 1 ]; then
LEVEL_NUM=$(map_level "$1")
set_console_level "$LEVEL_NUM"
echo "提示: 日志级别已调整,现在可以尝试加载驱动并观察输出"
echo "建议执行: modprobe npu_driver 或 insmod /path/to/npu_driver.ko"
echo "完整日志将保存至: $LOG_FILE"
else
echo "用法: $0 [debug|info|warn|error]"
echo "示例: $0 debug # 开启最详细日志,用于排查加载失败"
fi
# 捕获dmesg中与npu相关的最近日志
echo ""
echo "=== 最近NPU相关内核日志 ==="
dmesg | grep -i "npu\|npudrv" | tail -30 > "$LOG_FILE" 2>&1
if [ -s "$LOG_FILE" ]; then
cat "$LOG_FILE"
else
echo "(暂无NPU相关日志,驱动可能未加载或日志已被清除)"
fi
驱动加载失败排查流程
将上述脚本保存后赋予执行权限:chmod +x npu_log_config.sh。排查时按以下步骤操作:
- 以root身份运行
./npu_log_config.sh debug,将日志级别调至最高; - 执行
modprobe npu_driver(或实际驱动名)触发加载; - 观察终端输出或查看
/var/log/npu_driver_load.log; - 根据日志关键字定位根因:
firmware not found表示固件路径错误;resource busy表示IO地址或中断冲突;timeout表示硬件未就绪;unknown symbol表示依赖模块缺失。
验证方法与判定标准
验证步骤:
- 运行
./npu_log_config.sh(不带参数),确认输出显示当前日志级别; - 运行
./npu_log_config.sh debug,再次不带参数运行,确认级别已变为7; - 尝试加载驱动,观察是否出现比默认级别更详细的日志输出;
- 检查
/var/log/npu_driver_load.log文件是否已生成且包含时间戳和日志级别字段。
判定标准:
- 脚本能正确读取并修改
/proc/sys/kernel/printk中的日志级别值; - 设置
debug级别后,驱动加载时内核输出的信息量明显多于默认级别(出现INFO或DEBUG级条目); - 日志文件成功捕获包含
npu关键字的最近内核日志; - 若驱动加载失败,日志中能定位到具体错误原因(如文件缺失、资源冲突等),而非仅有笼统的
failed提示。
常见错误与日志特征对照
下表列出驱动加载失败的典型日志特征与对应根因,便于快速定位:
日志关键字 | 根因方向
------------------------------|-----------------------------
firmware not found | 固件文件缺失或路径配置错误
resource busy / conflict | IO地址、中断号或DMA通道冲突
unknown symbol | 依赖的内核模块未加载或版本不匹配
timeout / no response | 硬件未上电、PCIe链路异常或复位不完整
permission denied | 设备节点权限或SELinux策略限制
注意事项
日志级别设置仅对当前运行内核生效,重启后恢复默认值。若需持久化,可将echo "7 7" > /proc/sys/kernel/printk写入/etc/rc.local或systemd服务中。排查完成后建议将日志级别恢复为4,避免生产环境因大量调试日志影响性能。若驱动加载失败导致系统日志环形缓冲区被覆盖,可在加载前先执行dmesg -c清空缓冲区,确保捕获的日志从本次加载开始。