这里强烈推荐驱动开发者用这种方式输出log。linux kernel space中有pr_debug及dev_dbg来使用dynamic debug。可以看到当用户define DEBUG后,prdebug和dev_dbg就等于printk的KERN_DEBUG级别输出了;否则什么也不打印。
一. 开启dynamic debug功能
要使用dynamic_debug需要在kernel的defconfig中开启
CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y
用menuconfig去配置的话如下图:
二 dynamic debug功能使用
1. 编译好image后,需要挂载debugfs(不挂载的话将不会创建debugfs,那么/sys/kernel/debug/下是空的)。
修改etc/fstab文件,追加下面这段字符。
nodev /sys/kernel/debug debugfs defaults 0 0
2. 可以用cat /sys/kernel/debug/dynamic_debug/control | grep xxx.c来查看自己想要查看的log所在文件有没有包含进去。
那这里可以看到该文件所有用dev_dbg()打印出的讯息。
那如果不开启CONFIG_DYNAMIC_DEBUG,将不会产生/sys/kernel/debug/dynamic_debug目录, 是不能进行动态打印的。
开启dynamic debug:
①echo "module cvi_mipi_rx +p" > /sys/kernel/debug/dynamic_debug/control
②echo "file cvi_vip_cif.c +p" >/sys/kernel/debug/dynamic_debug/control
这两种方式都是开dynamic debug,第一种是对模块开启,第二种只对文件开启。下面举一个栗子:
开启之后,可以看到dev_dbg()打印的log都会输出。
反之,关闭dynamic debug:
①echo "module cvi_mipi_rx -p" > /sys/kernel/debug/dynamic_debug/control
②echo "file cvi_vip_cif.c -p" >/sys/kernel/debug/dynamic_debug/control
那除了上面的两种方式还有一种可以只开启某个function:
echo "func _init_resource +p" > /sys/kernel/debug/dynamic_debug/control
不过一般不太推荐使用这种做法,因为很多functions都是相同名字但属于不同modules的。
三 dev_err/dev_info/dev_warn系列函数
在Linux驱动代码中,有大量的调试信息,那么推荐使用dev_err/dev_info/dev_warn这一系列函数族。这一系列函数族定义在include/linux/device.h.
其实这些函数族本质上和下面printk.h中的定义也是完全一致的。
#define pr_emerg(fmt, ...)
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define pr_alert(fmt, ...)
printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_crit(fmt, ...)
printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...)
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...)
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warn pr_warning
#define pr_notice(fmt, ...)
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...)
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
下图是示例,可以看到err级别以下的log没有打印,那么设置printk的控制台级别可以把对应的log输出到console(如何设置printk console level可以看上一篇1. printk & dmesg)。
四 可变参数宏(##__VA_ARGS__)
##__VA_ARGS__表示可变参数宏,可以用来传递多个参数,如:
#define my_dbg(fmt, ...) do { printf("[%s] [%d] " fmt, __func__, __LINE__, ##__VA_ARGS__); } while(0) char *name = "robin"; int age = 18; my_dbg("this is a test. name:%s, age:%d ", name, age);
结果如下:
那和下面这种写法呢本质上是完全一样的。