Linux Kernel dynamic_debug
使用指南
在 Linux 内核中,dynamic_debug
是一个非常实用的功能,用于在运行时控制内核代码中的调试信息输出,而不需要重新编译或重启内核。dynamic_debug
提供了对 pr_debug()
和 dev_dbg()
调试信息的动态控制功能,使得开发人员可以根据需要打开或关闭某些模块中的调试信息,从而灵活地定位问题。
1. 动态调试的前置条件
为了使用动态调试功能,内核需要在编译时启用相关选项:
-
内核配置选项 :需要在内核配置中启用
CONFIG_DYNAMIC_DEBUG
,这样才会支持动态调试。CONFIG_DYNAMIC_DEBUG=y
2. 语法和用法
动态调试使用 /sys/kernel/debug/dynamic_debug/control
这个接口文件来控制调试信息输出。该文件包含了所有内核中使用了 pr_debug()
或 dev_dbg()
调试宏的条目,并且支持用户通过写入命令来启用或禁用这些调试信息。
要使用动态调试,首先需要挂载 debugfs
,例如:
bash
mount -t debugfs none /sys/kernel/debug
3. 查询调试信息
可以通过查看 /sys/kernel/debug/dynamic_debug/control
文件,来获取所有支持动态调试的条目:
bash
cat /sys/kernel/debug/dynamic_debug/control
这将显示内核中可用的调试信息条目,每一行对应一个调试语句。条目信息通常包括:
- 文件名
- 行号
- 模块名
- 函数名
- 状态(是否启用)
- 格式字符串
示例输出如下:
kernel/module.c:100 [module] module_param_call() =_ "Loading module: %s\n"
drivers/net/ethernet/eth.c:200 [eth] eth_open() =p "Opening Ethernet device\n"
字段说明:
文件名:行号
:调试信息所在的源文件和行号。[模块名]
:模块名称。函数名()
:所在的函数。状态符号
:用于表示当前调试状态,符号可能为=
或=p
,表示是否启用。格式字符串
:pr_debug()
或dev_dbg()
中的内容。
4. 动态控制调试信息
可以通过向 /sys/kernel/debug/dynamic_debug/control
写入命令来控制调试输出,常用的命令格式为:
file <filename> line <line_number> <flags>
module <module_name> <flags>
format <format_string> <flags>
其中,<flags>
可以是以下内容的组合:
p
:启用调试信息(print)。f
:在输出中显示函数名称。l
:在输出中显示行号。m
:在输出中显示模块名称。t
:在输出中显示时间戳。
例如:
-
启用某个文件中的所有调试信息:
bashecho 'file eth.c +p' > /sys/kernel/debug/dynamic_debug/control
这将启用
eth.c
文件中的所有pr_debug()
调试信息。 -
关闭某个模块中的所有调试信息:
bashecho 'module eth -p' > /sys/kernel/debug/dynamic_debug/control
这将关闭
eth
模块中的所有调试信息。 -
启用特定文件中特定行的调试信息:
bashecho 'file eth.c line 200 +p' > /sys/kernel/debug/dynamic_debug/control
这将启用
eth.c
文件中第 200 行的调试信息。 -
通过格式字符串启用调试信息:
bashecho 'format "Loading module*" +p' > /sys/kernel/debug/dynamic_debug/control
这将启用所有格式字符串中包含 "Loading module*" 的调试信息。
5. 持久化配置
动态调试的设置在重启后会丢失,因此可以将常用的配置添加到系统启动脚本中,比如 /etc/rc.local
,这样可以在系统启动时自动应用这些调试设置。
例如,添加以下内容到 /etc/rc.local
:
bash
echo 'module eth +p' > /sys/kernel/debug/dynamic_debug/control
6. 例子
假设你正在调试一个以太网驱动程序,你想查看驱动初始化过程中执行的调试信息,可以使用以下命令:
bash
echo 'module eth +p' > /sys/kernel/debug/dynamic_debug/control
然后加载驱动模块或重新启动网络服务,这样就可以看到内核日志中输出的调试信息。
如果你想临时关闭这些调试信息,只需运行:
bash
echo 'module eth -p' > /sys/kernel/debug/dynamic_debug/control
7. 实用技巧
-
与
dmesg
联合使用 :动态调试输出的调试信息通常会被写入内核日志中,因此可以使用dmesg
或journalctl
命令来查看调试输出。bashdmesg | grep eth
-
减少调试信息:可以只启用对某些特定路径、模块、或者行号的调试信息,减少不必要的信息干扰。
8. 总结
dynamic_debug
是 Linux 内核中非常灵活且强大的调试工具,它允许开发人员在不重启或重新编译内核的情况下动态地控制调试输出。通过它可以轻松启用或禁用特定模块或代码路径中的调试信息,从而帮助开发人员更高效地排查问题。
使用步骤总结如下:
- 确保内核配置开启了
CONFIG_DYNAMIC_DEBUG
选项。 - 挂载
debugfs
文件系统。 - 使用
/sys/kernel/debug/dynamic_debug/control
文件来查询和控制调试信息。 - 使用合适的命令启用或禁用调试信息,以更好地排查问题。