Linux驱动开发——pr_fmt的用法

作者:彭东林

邮箱:[email protected]

在阅读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.\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确实比较方便。

完。

时间: 2024-10-29 19:11:30

Linux驱动开发——pr_fmt的用法的相关文章

linux 驱动开发-模块的构建

1.模块的含义 linux 是采用模块化的方式构建的,允许内核在运行时动态地向其中插入或从中删除代码,这些代码(包扩函数,数据,模块入口函数,模块出口函数)被一并组合 在一个单独的二进制镜像,就是所谓的可装载内核模块. 模块可以是基本的内核镜像尽可能小,同时可以方便地对新功能进行调试,还可以实现热插拔(后续会学习如何实现设备的热插拔功能,暂时无需深究),和内核的核心子系统不一样,模块文件需要有入口点和出口点. 模块与应用程序的区别: a.模块和库函数类似,一个模块通常包含若干函数和数据,每个函数

linux驱动开发流程

嵌入式linux驱动开发流程嵌入式系统中,操作系统是通过各种驱动程序来驾驭硬件设备的.设备驱动程序是操作系统内核和硬件设备之间的接口,它为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,可以像操作普通文件一样对硬件设备进行操作.设备驱动程序是内核的一部分,完成以下功能:◇ 驱动程序的注册和注销.◇ 设备的打开和释放.◇ 设备的读写操作.◇ 设备的控制操作.◇ 设备的中断和轮询处理.Linux主要将设备分为三类:字符设备.块设备和网络设备.字符设备是指发送和接收数据以字符的

linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》

本文摘自本人拙著 <嵌入式Linux驱动模板精讲与项目实践> 初步看起来Linux设备驱动开发涉及内容非常多,而须要实现驱动的设备千差万别.事实上做一段时间驱动之后回首看来主要就是下面几点: (1)对驱动进行分类.先归纳为哪个类型的驱动.归类正确再利用内核提供的子系统进行开发,往往会发现事实上非常多通用的事情内核已经帮我们做了,一个优秀的驱动project师应该最大程度上利用内核的资源.内核已经实现的毕竟稳定性强.可移植性高. (2)找到内核的提供的子系统.接下来就是要制作该子系统对该类设备提

【转】linux驱动开发的经典书籍

原文网址:http://www.cnblogs.com/xmphoenix/archive/2012/03/27/2420044.html Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书为<linux_device_driver 3rd Edition>,这是一本很经典的书,无奈Linux的东东还是过于庞大,这本侧重于实战的书籍也只能停留在基本的接口介绍上,更深入的东东只能靠我们自己摸索了.但万事总有一个开头,没有对Linux驱动整体框架的把握是很难做一个优秀的驱动开发者的.除了

Linux 驱动开发笔记(一)

1.查看printk函数日记输出 (1)使用字符终端:通常使用ctrl+alt+f1切换查看: (2)使用cat /proc/kmsg命令:(在Linux系统启动后,/proc/kmsg文件可以查看内核对外所用的符号表,可以用cat命令查看器内容.) (3)使用dmesg命令查看. linux/kernel.h文件定义的printk函数的Log Level: 常数定义语句 意义 #define KERN_EMERG "<0>"/*系统不运行*/ #define KERN_A

Linux驱动开发 -- 打开dev_dbg()

Linux驱动开发 -- 打开dev_dbg() 2012-10-23 19:21:54 分类: LINUX linux设备驱动调试,我们在内核中看到内核使用dev_dbg来控制输出信息,这个函数的实质是调用printk(KERN_DEBUG )来输出打印信息.要打开这个开关需要下面两步. 1.打开调试开关:你调试的文件中必然包含了<linux/device.h>,或者<linux /paltforam_device.h>,后者包含了前者,在包含此头文件之前,使用#define D

s3c6410 Linux 驱动开发环境搭建

s3c6410 Linux 驱动开发环境搭建 -- 既然你是做Linux开发的,你还用虚拟机? 非常多人都在win下做开发,于是SD_writer.exe之类的烧写工具"大行其道",多是用虚拟机Linux. 全然转到Linux下学习開始蛮不爽的,开发板制作商送的教程都是些讲Win-CE的东东,感觉实质性的东西没什么.对于全然用Linux做开发的技术解说非常少,连烧写SD卡都用的win以下的程序.后来找了些资料,整理在这里,希望留给有心人.共同营造一个更好的共同学习的环境. 当别人遇到困

驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED

这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 不能再扯了,涉及到linux的驱动开发知识面灰常广,再扯文章就会变得灰常长.首先还是回到led驱动的本身上,自从linux被移植到arm上后,做驱动开发的硬件知识要求有所降低,很多都回归到了软件上,这是系统编程的一大特点,当然 ,也不排除有很多

嵌入式linux驱动开发之点亮led未遂(驱动编程思想之初体验)

有了上两篇文章的基础,我们就可以开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 另外实践很重要,一年多以前就知道了arm,那时整天用单片机的思维去yy着arm,直到前段时间弄来一块arm板,烧上linux系统后才知道,坑呀!根本不是那回事,所以实践是学习计算机类最重要的基本素质,如果整天看书,那基本上