如何打开pr_debug调试信息

本文介绍如何在Linux内核中启用pr_debug调试信息,包括定义DEBUG宏及使用动态调试方法。文章详细解释了pr_debug的不同实现方式,并指导读者如何通过修改配置选项和控制台级别来实现所需的调试输出。

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

如何打开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>好的,我现在要解决的问题是:如何在Android内核中启用pr_debug的输出。用户可能是一名Android开发者或者内核开发者,他们遇到了调试问题,希望通过pr_debug来输出调试信息,但发现默认情况下这些信息没有显示出来。需要找出正确的方法来开启这些调试日志。 首先,我得回忆一下pr_debug的工作原理。pr_debugLinux内核中通常是通过动态调试(dynamic debug)机制控制的,也就是说,默认情况下这些信息不会被打印到控制台或者日志中,除非明确启用。这可能涉及到内核配置选项、动态调试控制文件以及编译时的调试选项。 用户可能已经尝试过直接使用pr_debug,但发现没有输出,所以想知道如何正确配置。需要分步骤讲解,包括内核配置、编译选项、运行时启用方法,以及可能的注意事项。 首先,检查内核配置是否启用了CONFIG_DYNAMIC_DEBUG。这个选项是动态调试的基础,必须在内核配置中打开。用户可能需要进入内核源码目录,使用make menuconfig或者检查.config文件中的相关选项。 其次,编译内核时需要确保调试符号没有被优化掉。可能涉及到CONFIG_DEBUG_KERNEL和CONFIG_DEBUG_INFO选项,这些选项确保调试信息被包含在内核映像中。此外,pr_debug可能依赖于特定的宏定义,比如在包含printk.h之前定义DEBUG宏,或者在编译时通过DDEBUG标志启用。 然后,运行时控制。动态调试允许在运行时通过/sys/kernel/debug/dynamic_debug/control文件来控制哪些pr_debug语句被激活。例如,使用echo命令来启用特定文件的调试输出,或者使用通配符来启用所有。 另外,可能需要调整内核的printk日志级别,因为即使pr_debug被激活,如果日志级别设置过高,消息可能不会被显示。printk的日志级别有0到7,其中7是DEBUG级别,而默认的控制台日志级别可能较低,需要调整。 还有,可能需要使用dmesg命令来查看内核日志,或者确保日志缓冲区足够大,以便捕获调试信息。此外,不同版本的内核可能在配置上有所不同,尤其是Android内核可能有一些定制化的部分,需要注意是否有特定的补丁或配置选项。 用户可能遇到的问题包括:配置选项未正确开启、编译时未包含调试信息、运行时未正确激活动态调试、日志级别不够低、或者权限问题无法访问debugfs。需要逐一检查这些可能性,并给出具体的命令和步骤。 总结步骤应该是:配置内核开启动态调试和相关调试选项,重新编译并刷入内核,然后在运行时通过dynamic_debug接口启用特定的pr_debug输出,调整printk日志级别,最后使用dmesg查看输出。同时提醒用户注意内核版本差异和权限问题。</think>在 Android 内核中启用 `pr_debug` 输出需要多步骤配置,以下是详细操作指南: --- ### 一、内核配置准备 #### 1. 开启动态调试支持 ```bash # 在内核源码目录执行 make menuconfig # 定位配置项 Kernel hacking -> -> printk and dmesg options [*] Enable dynamic printk() support (CONFIG_DYNAMIC_DEBUG) [*] Debugging data visibility (选择合适调试级别) ``` #### 2. 关键配置项验证 检查 `.config` 文件需包含: ```ini CONFIG_DYNAMIC_DEBUG=y # 动态调试核心支持 CONFIG_DEBUG_FS=y # debugfs 文件系统支持 CONFIG_DEBUG_INFO=y # 保留调试符号 ``` --- ### 二、编译时调试启用 #### 1. 源文件级调试激活 在需要调试的 C 文件顶部添加: ```c #define DEBUG // 必须在包含 printk.h 之前定义 #include <linux/printk.h> ``` #### 2. 全局调试编译(可选) 在 Makefile 中添加编译标志: ```makefile EXTRA_CFLAGS += -DDEBUG # 开启该文件所有调试 # 或 EXTRA_CFLAGS += -DVERBOSE_DEBUG # 某些驱动专用调试宏 ``` --- ### 三、运行时调试控制 #### 1. 挂载 debugfs ```bash adb shell su mount -t debugfs none /sys/kernel/debug ``` #### 2. 动态启用调试输出 ```bash # 激活特定文件的调试 echo 'file xxx.c +p' > /sys/kernel/debug/dynamic_debug/control # 激活整个模块的调试 echo 'module xyz +p' > /sys/kernel/debug/dynamic_debug/control # 激活所有调试(谨慎使用) echo 'func pr_debug +p' > /sys/kernel/debug/dynamic_debug/control ``` #### 3. 查看当前调试状态 ```bash cat /sys/kernel/debug/dynamic_debug/control | grep enabled ``` --- ### 四、日志系统配置 #### 1. 调整 printk 日志级别 ```bash # 设置控制台输出最低级别为 DEBUG (7) echo 8 > /proc/sys/kernel/printk # 7 | 4 | 1 | 7 格式 ``` #### 2. 查看完整调试输出 ```bash adb shell dmesg -wH | grep -i "你的调试标记" ``` --- ### 五、Android 特殊注意事项 #### 1. 内核版本差异处理 | 内核版本 | 特性差异 | |---------|---------| | < 4.9 | 需要手动启用每个调试点 | | ≥ 4.19 | 支持通配符批量激活 | #### 2. 权限问题解决 ```bash # 针对 eng 版本系统 adb root adb remount # userdebug 版本可能需要: setenforce 0 ``` --- ### 六、调试验证示例 ```c // 内核代码示例 void critical_function(void) { pr_debug("CPU[%d] 进入关键路径", smp_processor_id()); // ... 业务逻辑 } ``` 执行验证命令: ```bash echo 'file driver/xyz/core.c +p' > /sys/kernel/debug/dynamic_debug/control adb shell dmesg -c > /dev/null # 清空日志 # 触发相关功能 adb shell dmesg | grep "进入关键路径" ``` --- ### 七、常见问题排查 1. **无输出情况处理** - 检查 `/proc/cmdline` 是否包含 `debug` 参数 - 确认驱动未使用 `pr_devel` 替代 `pr_debug` - 验证编译时是否优化掉了调试代码(检查反汇编) 2. **性能影响警告** ```bash # 高频调试语句建议添加频率限制 if (printk_ratelimit()) pr_debug("高频事件: count=%d\n", ++count); ``` --- 通过以上步骤,可以精确控制 `pr_debug` 的输出范围和详细程度。建议在开发阶段使用模块化调试策略,生产环境中及时关闭调试功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值