博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何打开pr_debug调试信息
阅读量:6715 次
发布时间:2019-06-25

本文共 4950 字,大约阅读时间需要 16 分钟。

转载:

以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的用法
1.如果定义了CONFIG_DYNAMIC_DEBUG,就使用动态debug机制dynamic_pr_debug();
2.如果定义了DEBUG,就使用printk(KERN_DEBUG...)
3.默认情况下,不打印。
那么要想让kernel乖乖的打印调试信息,就只有两条路可选了:要么动态debug,要么定义DEBUG宏。
先说一下如何定义DEBUG宏
其实在kernel中很多driver已经定义好了这样的选项
例如,我们经常可以看到这样的配置选项和宏定义:
(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/printk7       4       1       7$echo 8 > /proc/sys/kernel/printk$cat /proc/sys/kernel/printk8       4       1       7

 

ok,大功告成!

ps:如果一些driver没有现成的宏可用,开发人员可以自己仿照上述方法,也可以直接在源文件中定义DEBUG宏

#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之旅吧!

下面是一个范例

Makefile:

ifneq ($(KERNELRELEASE),)    ccflags-y += -DDEBUG    obj-m := debug_driver.o    obj-m += debug_device.oelse    KERNELDIR ?= /root/work/latest_codes/linux-stable    PWD := $(shell pwd)default:    $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:    @rm -rf *.o *.mod.c *.mod.o *.ko *.order *.symvers .*.cmd .tmp_versionsendif

 

debug_device.c

#include 
#include
#include
#include
#include
MODULE_LICENSE("GPL");static void demo_release (struct device *dev) {}static struct platform_device demo_dev = { .name = "demo_debug", .id = -1, .dev = { .release = demo_release, },};static int demo_init(void){ platform_device_register(&demo_dev); return 0;}

 

debug_driver.c

#include 
#include
#include
#include
#include
#include
#include
#include
static struct device *dev = NULL;static int debug_demo_open (struct inode *inode, struct file *file) { pr_debug("pr_debug: \n"); dev_dbg(dev, "dev_dbg test.\n"); return 0;}static int debug_demo_close (struct inode *inode, struct file *file) { printk("%s enter.\n", __func__); return 0;}static ssize_t debug_demo_write (struct file *file, const char __user *buf, size_t size, loff_t *offset) { printk("%s enter, size: %d\n", __func__, size); return size;}static struct file_operations debug_demo_fops = { .owner = THIS_MODULE, .open = debug_demo_open, .write = debug_demo_write, .release = debug_demo_close,};static struct miscdevice debug_demo_miscdev = { MISC_DYNAMIC_MINOR, "debug_demo", &debug_demo_fops};static int demo_probe(struct platform_device *device) { int ret; printk("%s enter.\n", __func__); dev = &device->dev; ret = misc_register(&debug_demo_miscdev); printk("ret: %d\n", ret); if (ret < 0) return ret; return 0;}static struct platform_driver demo_driver = { .probe = demo_probe, .driver = { .name = "demo_debug", .owner = THIS_MODULE, },};static int demo_init(void){ platform_driver_register(&demo_driver); printk(KERN_ALERT "demo World.\n"); return 0;}static void demo_exit(void){ platform_driver_unregister(&demo_driver); misc_deregister(&debug_demo_miscdev); printk(KERN_ALERT "GoodBye, cruel world.\n");}MODULE_LICENSE("GPL");module_init(demo_init);module_exit(demo_exit);

完。

你可能感兴趣的文章
[学习笔记]Spring依赖注入
查看>>
网络虚拟化(SDN,NFV..)和企业骨干网的演化
查看>>
怎么确保站点的可用性
查看>>
我的第一个android应用——装逼神器《微博尾》
查看>>
[3] MQTT,mosquitto,Eclipse Paho---怎样使用 Eclipse Paho MQTT工具来发送订阅MQTT消息?
查看>>
jsTree插件简介(三)
查看>>
[PHP] 通用网关接口CGI 的运行原理
查看>>
phoenixframe自己主动化平台在Linux环境下运行用例的说明
查看>>
Linux:sheel脚本for的用法,及日期参数+1day用法
查看>>
函数式编程
查看>>
spring boot mybatis没有扫描jar中的Mapper接口
查看>>
ijkPlayer 集成
查看>>
Python 文件 writelines() 方法
查看>>
背水一战 Windows 10 (76) - 控件(控件基类): Control - 基础知识, 焦点相关, 运行时获取 ControlTemplate 和 DataTemplate 中的元素...
查看>>
图像滤镜艺术---Glow Filter发光滤镜
查看>>
create-react-app 引入 antd 及 解决 antd 样式无法显示的bug
查看>>
获取图形验证码
查看>>
Fresco-Facebook的图片加载框架的使用
查看>>
Android Runtime Stats
查看>>
InstallShield卸载状态
查看>>