Linux驱动开发之使用dev_dbg调试设备驱动



原创作品,转载时请务必以超链接形式标明文章原始出处:http://blog.csdn.net/gqb666/article/details/8789807,作者:gqb666

1、最近在写I2C下EEPROM的驱动程序,但发现使用i2c_new_probed_device函数无法枚举到设备,于是想调试该函数(位于driver/i2c/i2c-core.c内),看到其中有些调试信息如下:

  1. i2c_new_probed_device(...)  
  2. {  
  3.     ...  
  4.     if (addr_list[i] == I2C_CLIENT_END) {  
  5.         dev_dbg(&adap->dev, "Probing failed, no device found\n");  
  6.         return NULL;  
  7.     }  
  8.     ...  
  9. }  
但加载驱动模块,该类调试信息并未打印出来(执行dmesg命令后同样未找到调试信息)。

2、列出dev_dbg源码实现:(include/linux/device.h中)

  1. #if defined(DEBUG)  
  2. #define dev_dbg(dev, format, arg...)        \  
  3.     dev_printk(KERN_DEBUG , dev , format , ## arg)  

问题找出,只需在引用头文件#include/linux/device.h前定义DEBUG宏即可。

在include/linux/i2c.h中修改代码如下:

  1. #define DEBUG                  /* add for debug eeprom */  
  2. #include <linux/device.h> /* for struct device */  
  3. #undef DEBUG                   /* add for debug eeprom */  

加载驱动驱动模块后,并没有调试信息打印出。如下图:


但执行dmesg命令后Probing failed, no device found已经能够打印出来,如下图:


这是为什么呢?

3、注意dev_printk的打印级别:

  1. dev_printk(KERN_DEBUG , dev , format , ## arg)  
这里有个KERN_DEBUG的打印级别,其他级别如下(include/linux/kern_levels.h中):
#define KERN_EMERG	KERN_SOH "0"	/* system is unusable */
#define KERN_ALERT	KERN_SOH "1"	/* action must be taken immediately */
#define KERN_CRIT	KERN_SOH "2"	/* critical conditions */
#define KERN_ERR	KERN_SOH "3"	/* error conditions */
#define KERN_WARNING	KERN_SOH "4"	/* warning conditions */
#define KERN_NOTICE	KERN_SOH "5"	/* normal but significant condition */
#define KERN_INFO	KERN_SOH "6"	/* informational */
#define KERN_DEBUG	KERN_SOH "7"	/* debug-level messages */


可以看到KERN_DEBUG级别最低为7。
再看/include/linux/printk.h下的一个宏:

  1. #define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */
该行表示只有打印级别高于DEFAULT_CONSOLE_LOGLEVEL(值小于DEFAULT_CONSOLE_LOGLEVEL的值)的打印才会出现在终端上。而 KERN_DEBUG也为7,所以我们的调试不会直接打印出来。

将该行修改为:

  1. #define CONSOLE_LOGLEVEL_DEFAULT 8 /* anything MORE serious than KERN_DEBUG */
来保证KERN_DEBU的值小于DEFAULT_CONSOLE_LOGLEVEL,然后加载eeprom驱动模块后:调试信息能够正确打印出来。






在内核中经常见到一些调试打印信息。pr_debug,pr_err等。以前的理解是以为只有出错才会将pr_err中的内容打印出来,现在看来是错的。pr_err并不等同与perror。

关于pr_err,pr_debug的定义有两种:


第一种

(tools\perf\util\debug.h)

int eprintf(int level,
        const char *fmt, ...) __attribute__((format(printf, 2, 3)));

#define pr_err(fmt, ...) \
    eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)

#define pr_warning(fmt, ...) \
    eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...) \
    eprintf(0, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_debug(fmt, ...) \
    eprintf(1, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_debugN(n, fmt, ...) \
    eprintf(n, pr_fmt(fmt), ##__VA_ARGS__)

#define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)

第二种

(tools\virtio\linux\kernel.h)

#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
#ifdef DEBUG
#define pr_debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
#else
#define pr_debug(format, ...) do {} while (0)
#endif
#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)


第一种定义,可以看出pr_err,pr_debug,pr_warning,pr_info实质上都是一样的,eprintf就是printf函数。__attribute__((format(printf, 2, 3)));表示printf格式化字符串从printf的第2个参数开始,可变参数从printf的第3个参数开始。关于attribute的介绍可以参加这里

所以,对于内核代码中出现pr_err,pr_debug,pr_warning,pr_info都是打印信息到终端。


第二种定义,关键是对fprintf的理解了。

<span style="font-size:18px;">fprintf(stderr, "Can't open it!\n");
fprintf(stdout, "Can't open it!\n");</span>
<span style="font-size:18px;">stdout -- 标准输出设备 (printf("..")) 同 stdout。
stderr -- 标准错误输出设备
两者默认向屏幕输出。
但如果用转向标准输出到磁盘文件,则可看出两者区别。stdout输出到磁盘文件,stderr在屏幕。</span>
也就是说两者都是要向终端屏幕打印信息的。

【总结】:pr_err pr_debug等调用时,都会打印到终端屏幕的,不管之前的语句是否发生错误。之所以有几种定义,是为了代码清晰。



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值