Linux内核 -- `dynamic_debug` 使用指南

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:在输出中显示时间戳。

例如:

  1. 启用某个文件中的所有调试信息

    bash 复制代码
    echo 'file eth.c +p' > /sys/kernel/debug/dynamic_debug/control

    这将启用 eth.c 文件中的所有 pr_debug() 调试信息。

  2. 关闭某个模块中的所有调试信息

    bash 复制代码
    echo 'module eth -p' > /sys/kernel/debug/dynamic_debug/control

    这将关闭 eth 模块中的所有调试信息。

  3. 启用特定文件中特定行的调试信息

    bash 复制代码
    echo 'file eth.c line 200 +p' > /sys/kernel/debug/dynamic_debug/control

    这将启用 eth.c 文件中第 200 行的调试信息。

  4. 通过格式字符串启用调试信息

    bash 复制代码
    echo '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 联合使用 :动态调试输出的调试信息通常会被写入内核日志中,因此可以使用 dmesgjournalctl 命令来查看调试输出。

    bash 复制代码
    dmesg | grep eth
  • 减少调试信息:可以只启用对某些特定路径、模块、或者行号的调试信息,减少不必要的信息干扰。

8. 总结

dynamic_debug 是 Linux 内核中非常灵活且强大的调试工具,它允许开发人员在不重启或重新编译内核的情况下动态地控制调试输出。通过它可以轻松启用或禁用特定模块或代码路径中的调试信息,从而帮助开发人员更高效地排查问题。

使用步骤总结如下:

  1. 确保内核配置开启了 CONFIG_DYNAMIC_DEBUG 选项。
  2. 挂载 debugfs 文件系统。
  3. 使用 /sys/kernel/debug/dynamic_debug/control 文件来查询和控制调试信息。
  4. 使用合适的命令启用或禁用调试信息,以更好地排查问题。
相关推荐
lida200310 分钟前
无人机救援系统简单解读
linux·无人机·openipc·wfb-ng
0725游广川1 小时前
cjson内存泄漏问题注意事项
服务器·json
TensorFlowGAN3 小时前
rhcsa、ce复习(每日编辑,复习完为止)
linux·es
Drscq4 小时前
How to migrate a CentOS 8 to Rocky Linux 8.10
linux·运维·centos
修心光4 小时前
CentOS配置iptables规则并使其永久生效
linux·运维·centos
加载中loading...4 小时前
Linux线程安全(二)条件变量实现线程同步
linux·运维·服务器·c语言·1024程序员节
安科瑞刘鸿鹏4 小时前
校园建筑用电安全监测装置 电气火灾监测预防设备功能介绍
运维·服务器·网络·嵌入式硬件·安全·能源
课堂随想4 小时前
【libGL error】Autodl云服务器配置ACT的conda虚拟环境生成训练数据时,遇到了libGL相关错误,涉及swrast_dri.so
运维·服务器·conda
画江湖Test5 小时前
SDK如何测试
服务器·sdk
well_fly7 小时前
Ubuntu特殊目录
linux·ubuntu