zoukankan      html  css  js  c++  java
  • Linux驱动开发——pr_fmt的用法

    作者:彭东林

    邮箱:pengdonglin137@163.com

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

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

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

    #define pr_fmt(fmt) "i2c-core: " fmt
    
    #include <dt-bindings/i2c/i2c.h>
    #include <asm/uaccess.h>
    #include <linux/acpi.h>
    ... ...

    但是在这个文件中并没有看到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_fmt
     3 #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 defined
    10  * 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 <linux/dynamic_debug.h>
    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.
    ", __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确实比较方便。

    完。

  • 相关阅读:
    IIS服务器应用程序不可用的解决办法
    C#几个经常犯错误汇总
    C1flexgrid格式化
    图片自动按比例缩小代码(防止页面被图片撑破)
    VSS2005的使用与配置过程
    ASP.NET通过IHttpModule实现伪静态
    五一游玩收藏
    plants
    几个JS的方法
    英式英语VS美式英语的差异
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/6209424.html
Copyright © 2011-2022 走看看