fmt函数linux,Linux驱动开发——pr_fmt的用法

作者:彭东林

在阅读kernel代码的时候,总是看到有很多驱动都在第一行定义pr_fmt,闲来没事,分析了一下, 发现,确实挺方便的。下面记录分享一下。

我们知道,在驱动中可以使用dev_dbg来输出log,在输出的log中会有一些额外的信息,如所属的device的name。

而pr_fmt就可以实现这个目的,先看一个用法(drivers/i2c/i2c-core.c):

#define pr_fmt(fmt) "i2c-core: " fmt#include#include#include... ...

但是在这个文件中并没有看到pr_fmt被使用。然后,猜测应该是被哪个宏使用了,所以我在include下搜索pr_fmt发现:

include/linux/printk.h:271: printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:273: printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:275: printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:277: printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:279: printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:282: printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:284: printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)

include/linux/printk.h:296: printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)

然后看一下printk.h:

1 ... ...2 #ifndef pr_fmt3 #define pr_fmt(fmt) fmt

4 #endif

5

6 /*

7 * These can be used to print at the various log levels.8 * All of these will print unconditionally, although note that pr_debug()9 * and other debug macros are compiled out unless either DEBUG is defined10 * or CONFIG_DYNAMIC_DEBUG is set.11 */

12 #define pr_emerg(fmt, ...) 13 printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)14 #define pr_alert(fmt, ...) 15 printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)16 #define pr_crit(fmt, ...) 17 printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)18 #define pr_err(fmt, ...) 19 printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)20 #define pr_warning(fmt, ...) 21 printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)22 #define pr_warn pr_warning

23 #define pr_notice(fmt, ...) 24 printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)25 #define pr_info(fmt, ...) 26 printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)27

28 #if defined(CONFIG_DYNAMIC_DEBUG)

29 #include

30

31 /*dynamic_pr_debug() uses pr_fmt() internally so we don‘t need it here*/

32 #define pr_debug(fmt, ...) 33 dynamic_pr_debug(fmt, ##__VA_ARGS__)34 #elif defined(DEBUG)

35 #define pr_debug(fmt, ...) 36 printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)37 #else

38 #define pr_debug(fmt, ...) 39 no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)40 #endif

41 ... ...

可以看到,如果驱动中没有定义pr_fmt(fmt),那么,pr_fmt(fmt)就是fmt。

使用pr_fmt的还不少, 这里有几个比较常用的函数: pr_err, pr_info,  如果没有定义CONFIG_DYNAMIC_DEBUG, 那么pr_debug也会使用pr_fmt。

从上面的代码已经看到pr_fmt的作用了吧,就是在用户要输出的log前面添加额外的固定的信息。下面结合gpio_demo.c驱动看一下pr_fmt的几种用法:

1 #define pr_fmt(fmt) "gpio_demo: " fmt

2 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

3 #define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__

在gpio_demo.c的第一行定义上面的一种, 然后, 在驱动中调用pr_info, 如:

1 static int gpio_demo_probe(struct platform_device *pdev) {2 struct device *dev = &pdev->dev;3 int ret = 0;4 int i = 0;5 int gpio = -1;6 gpio_demo_data_t *data =NULL;7 struct resource *res =NULL;8 u32 config, pud, drv;9

10 pr_info("%s enter.\n", __func__);11 ... ...

下面是 #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.

这对输出log确实比较方便。

完。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值