printk学习之(三):你还在用printk吗?

1.printk的继任者pr_xxx系列函数

前面两节我们介绍了printk的基本原理和printk在驱动调试中的用法,现在我们看一下printk的继任者,pr_xxx系列函数

可以看到,如果没有定义pr_fmt(fmt),那么pr_fmt(fmt)就是fmt,这样的话pr_xxx系列函数仅仅是一个printk的简单封装

但是精髓在于可以自己定义pr_fmt(fmt),让我们封装成自己的打印函数,方便调试

... ...
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

/*
 * These can be used to print at the various log levels.
 * All of these will print unconditionally, although note that pr_debug()
 * and other debug macros are compiled out unless either DEBUG is defined
 * or CONFIG_DYNAMIC_DEBUG is set.
 */
#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__)
... ...
#define	KERN_EMERG	"<0>"	/* system is unusable			*/
#define	KERN_ALERT	"<1>"	/* action must be taken immediately	*/
#define	KERN_CRIT	"<2>"	/* critical conditions			*/
#define	KERN_ERR	"<3>"	/* error conditions			*/
#define	KERN_WARNING	"<4>"	/* warning conditions			*/
#define	KERN_NOTICE	"<5>"	/* normal but significant condition	*/
#define	KERN_INFO	"<6>"	/* informational			*/
#define	KERN_DEBUG	"<7>"	/* debug-level messages			*/

 2.pr_xxx系列函数的好处

可以给用户要输出的log前面添加额外的固定的信息,方便调试

下面给出参考博客中的一些用法:(自己的宏定义要写在文件的第一行定义pr_fmt)

/* 
 * #define pr_fmt(fmt) "gpio_demo: " fmt
 * #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 * #define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__
 */
#include xxx
... ...
static int gpio_demo_probe(struct platform_device *pdev) {
   ... ...
    pr_info("%s enter.\n", __func__);
   ... ...
}

下面是 #define pr_fmt(fmt) "gpio_demo: " fmt 的输出:

[ 1022.623230] gpio_demo: gpio_demo_probe enter.

下面是 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 的输出(KBUILD_MODNAME是模块的名字,可以阅读这个驱动文件的Makefile文件获得):

[ 1088.639631] gpio_demo: gpio_demo_probe enter.

下面是 #define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__ 的输出:

[ 1135.108534] gpio_demo:gpio_demo_probe:87: gpio_demo_probe enter.

3.注意事项

当然,也不一定非得在文件的第一行进行宏定义,也可以在需要的地方:

#undef pr_fmt(fmt)移除宏定义,然后再自行定义

参考博客:https://www.cnblogs.com/pengdonglin137/p/6209424.html

 

 

你可能感兴趣的:(驱动学习)