Linux 内核动态打印机制详解
在 Linux 内核开发和调试过程中,日志输出是最重要的工具之一。常见的日志接口包括 pr_info()、pr_err()、pr_debug() 以及设备相关的 dev_info()、dev_err()、dev_dbg() 等。其中,dev_dbg() 和 pr_debug() 默认情况下往往不会直接打印出来,它们依赖于 动态调试 (Dynamic Debug) 机制。
一、CONFIG_DYNAMIC_DEBUG 配置
要使用动态调试,首先需要在内核编译时启用相关配置:
text
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_FS=y
其中:
CONFIG_DYNAMIC_DEBUG:开启动态调试支持。CONFIG_DEBUG_FS:提供 debugfs 文件系统接口,动态调试依赖它来控制。
编译完成后,确保系统挂载了 debugfs:
bash
mount -t debugfs none /sys/kernel/debug
二、动态调试的控制接口
动态调试的核心接口是:
text
/sys/kernel/debug/dynamic_debug/control
这个文件包含了所有支持动态调试的调用点(例如 dev_dbg()),可以通过写入规则来开启或关闭。
常见用法
- 按文件启用
bash
echo 'file drivers/usb/core/hub.c +p' > /sys/kernel/debug/dynamic_debug/control
开启 hub.c 文件中所有 dev_dbg() 的打印。
- 按函数启用
bash
echo 'func hub_power_on +p' > /sys/kernel/debug/dynamic_debug/control
只开启 hub_power_on() 函数中的调试信息。
- 按模块启用
bash
echo 'module usbcore +p' > /sys/kernel/debug/dynamic_debug/control
开启 usbcore 模块的所有调试信息。
- 按行号范围启用
bash
echo 'file hub.c line 880-900 +p' > /sys/kernel/debug/dynamic_debug/control
只开启指定行号范围内的调试信息。
标志说明
+p:启用打印-p:关闭打印+f:显示函数名+m:显示模块名+l:显示行号
三、启动参数方式
除了运行时控制,还可以在内核启动参数中直接启用:
text
dyndbg="file drivers/usb/core/hub.c +p"
这样系统启动时就会自动打开对应文件的调试日志。
四、模块加载参数
对于可加载模块,可以在 modprobe 时指定:
bash
modprobe mydriver dyndbg="file mydriver.c +p"
五、日志等级与显示
dev_dbg() 属于 KERN_DEBUG 级别日志,如果要在控制台看到,需要调整 loglevel:
bash
dmesg -n 8
否则日志只会保存在内核缓冲区中,通过 dmesg 查看。