如何打开pr_debug调试信息

本文详细介绍如何在Linux内核中开启和使用pr_debug调试信息,包括定义DEBUG宏、调整console级别和利用动态调试接口的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自https://blog.youkuaiyun.com/helloanthea/article/details/25330809

如何打开pr_debug调试信息,先不要着急,我们先静下心来分析一下这个函数的源代码。。。

以DMA的调试为例,先来看看一个pr_debug函数调用

       pr_debug("%s: %s (%s)\n",
                 __func__,
                 chan ? "success" : "fail",
                 chan ? dma_chan_name(chan) : NULL);

在include/linux/printk.h里找到pr_debug的定义,这里暗藏了玄机。
/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG)
/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
#define pr_debug(fmt, ...) \
        dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
        printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \
        no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

原来,三个宏作为判断条件决定了pr_debug到底采用哪种用法:
第一种用法,如果定义了CONFIG_DYNAMIC_DEBUG,就使用动态debug机制dynamic_pr_debug();
第二种用法,如果定义了DEBUG,就使用printk(KERN_DEBUG...)
第三种用法,默认情况下,不打印。

第三种不打印肯定不是我们想要的,那么要想让kernel乖乖的打印调试信息,就只有前面两条路可选了:要么动态debug,要么定义DEBUG宏。

先说一下如何定义DEBUG宏:
其实在kernel中很多driver已经定义好了这样的DEBUG选项,前人栽树,后人乘凉,我们可以先看看有没有现成的
例如,我们经常可以看到这样的配置选项和宏定义:
(1)DMA Engine debugging(CONFIG_DMADEVICES_DEBUG )
(2)Power Management Debug Support(CONFIG_PM_DEBUG)
(3) Enable debug for the B2C2 FlexCop drivers(CONFIG_PCI_DEBUG)

以DMA为例,在drivers/dma/Makefile中定义了编译选项
ccflags-$(CONFIG_DMADEVICES_DEBUG)  := -DDEBUG
其作用相当于在drivers/dma/所有子文件定义了宏#define DEBUG

小伙伴们赶紧把CONFIG_DEBUG选项选上吧,然后重新编译kernel。先别急,这样还不够,
默认的console级别是7(在kernel/printk/printk.c中定义了#define DEFAULT_CONSOLE_LOGLEVEL 7)
只有那些级别“小于7”的调试信息才能打印出来,而printk(KERN_DEBUG...)的级别是7,那就还需要提高console打印级别
如果要查看dma初始化的debug信息,那就直接改代码
#define DEFAULT_CONSOLE_LOGLEVEL 8
如果是runtime,可以直接通过printk的sys接口调整打印级别
$cat /proc/sys/kernel/printk
7       4       1       7
$echo 8 > /proc/sys/kernel/printk
$cat /proc/sys/kernel/printk
8       4       1       7

ok,大功告成!

如果一些driver没有现成的宏可用,那么你可以在你想debug的源文件中直接定义DEBUG宏,例如你想查看driver/video/fsl-diu-fb.c的调试信息,直接在头文件引用后添加宏定义

#define DEBUG(宏的作用范围相信我就不用多说了吧,就是从宏定义开始到源文件的末尾结束),就能如愿以偿了。

开发人员也可以自己仿照上述方法进行定义。

下面再简单说一下kernel的动态调试
打开Enable dynamic printk() support(DYNAMIC_DEBUG),那么所有的 pr_debug()/dev_debug() 之类的函数在runtime就可以动态地使用了。
kernel动态调试提供一个debugfs接口: <debugfs>/dynamic_debug/control 
这个文件可以用来获取已完成的调试信息列表
例如你要显示文件'svcsock.c'的1603行内容,你可以这样做:

nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
                <debugfs>/dynamic_debug/control  

// 提供文件svcsock.c所有信息 
nullarbor:~ # echo -n 'file svcsock.c +p' >
                <debugfs>/dynamic_debug/control 

如果你想执行多个命令,你需要为每个加入“echo”分割,像这样:

nullarbor:~ # echo 'file svcsock.c line 1603 +p' > /proc/dprintk ;\
> echo 'file svcsock.c line 1563 +p' > /proc/dprintk

或者甚至是这样: 

nullarbor:~ # (
> echo 'file svcsock.c line 1603 +p' ;\
> echo 'file svcsock.c line 1563 +p' ;\
> ) > /proc/dprintk 

file可以替换成module,format等匹配方式,具体用法请参考Documentation/dynamic-debug-howto.txt
好了,enjoy你的debug之旅吧!

<think>好的,用户问的是如何打开pr_debug日志。首先,我需要确定pr_debug在Linux内核中的使用场景。pr_debug是内核中的宏,用于调试信息输出,但默认情况下可能不会打印出来。用户可能需要知道如何在内核中启用这些调试日志。首先,我应该回忆pr_debug的工作原理。它依赖于动态调试功能,可能通过CONFIG_DYNAMIC_DEBUG编译选项启用。用户需要在内核配置中启用这个选项,并且在编译时加上DEBUG定义。此外,动态调试可以通过/sys/kernel/debug/dynamic_debug/control文件来控制哪些模块和文件的调试信息被输出。接下来,用户可能需要具体的步骤,比如如何修改Makefile,如何在内核启动时传递参数,或者如何通过sysfs在运行时启用调试日志。需要分步骤说明,包括编译时和运行时的配置。然后,考虑用户可能的实际应用场景。例如,调试某个特定驱动或模块,可能需要示例代码来展示pr_debug的使用,以及如何针对特定文件启用调试信息。同时,用户可能需要知道如何检查哪些调试语句是活跃的,使用dmesg命令查看日志。另外,用户可能对性能影响有疑问,需要提醒启用调试日志可能带来的性能开销,以及在生产环境中应谨慎使用。同时,可能需要注意不同内核版本的差异,比如旧版本是否支持动态调试,或者是否需要其他配置。 最后,应该总结关键步骤,并给出相关问题,帮助用户深入理解动态调试机制,比如如何过滤特定模块、动态调试的sysfs接口使用,pr_debug与其他日志宏的区别,以及如何在内核启动参数中设置调试选项。</think>### 回答问题 #### 在 Linux 内核中启用 `pr_debug()` 日志的 **3 种方法** 和 **2 种调试技巧**: --- ### 核心方法 1. **动态调试控制**(推荐方案): ```bash # 查看所有可调试点 grep "pr_debug" /sys/kernel/debug/dynamic_debug/control # 启用特定文件的调试 echo 'file drivers/usb/core/* +p' > /sys/kernel/debug/dynamic_debug/control ``` 2. **编译时强制启用**: ```makefile # 在Kconfig中确保配置生效 CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_FS=y # 在Makefile中添加编译选项 EXTRA_CFLAGS += -DDEBUG ``` 3. **内核启动参数**: ```text // 在GRUB配置中添加 dyndbg="file drivers/net/ethernet/* +p" ``` --- ### 代码示例 #### 典型调试代码模式 ```c #include <linux/printk.h> void usb_device_probe(struct device *dev) { pr_debug("Probing device %s\n", dev_name(dev)); // 默认不输出 if (unlikely(debug_enabled)) { pr_debug("Detailed register dump:\n"); dump_registers(dev); } } ``` #### 动态调试查询命令 ```bash # 查看所有活跃的调试语句 cat /sys/kernel/debug/dynamic_debug/control | grep "pr_debug" # 输出示例 drivers/usb/core/hub.c:1455 [usb_hub_init]pr_debug =_ "hub_configure\n" ``` --- ### 给出解释 1. **动态调试原理**: - 通过 `/sys/kernel/debug/dynamic_debug/control` 接口动态控制 - `+p` 表示启用打印,`-p` 表示禁用 - 支持通配符匹配(`*` 表示任意字符,`?` 表示单个字符) 2. **调试技巧**: - **模块级控制**:`echo "module usbcore +p" > /sys/kernel/debug/dynamic_debug/control` - **行号限定**:`echo "file drivers/usb/core/hub.c line 1480-1500 +p"` 3. **日志查看方法**: ```bash dmesg -H --color=always | grep -i "usb probe" journalctl -k --grep="pr_debug" ``` --- ### 调试标记说明 | 控制标记 | 功能描述 | |---------|---------| | `+p` | 启用打印 | | `-p` | 禁用打印 | | `+l` | 添加行号 | | `+m` | 显示模块名 | | `+t` | 显示线程ID | --- ### 性能注意事项 1. **生产环境警告**: ```bash # 禁用所有调试 echo "-p" > /sys/kernel/debug/dynamic_debug/control ``` 2. **选择性启用**: ```bash # 仅启用错误路径调试 echo "func handle_error +p" > /sys/kernel/debug/dynamic_debug/control ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值