作者:彭东林

邮箱: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::    printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
include/linux/printk.h:: printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)

然后看一下printk.h:

 ... ...
#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__) #if defined(CONFIG_DYNAMIC_DEBUG)
#include <linux/dynamic_debug.h> /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
#define pr_debug(fmt, ...) \
dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
... ...

可以看到,如果驱动中没有定义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的几种用法:

 #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__

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

 static int gpio_demo_probe(struct platform_device *pdev) {
struct device *dev = &pdev->dev;
int ret = ;
int i = ;
int gpio = -;
gpio_demo_data_t *data = NULL;
struct resource *res = NULL;
u32 config, pud, drv; 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.

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

完。

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

  1. 嵌入式Linux驱动开发日记

    嵌入式Linux驱动开发日记 主机硬件环境 开发机:虚拟机Ubuntu12.04 内存: 1G 硬盘:80GB 目标板硬件环境 CPU: SP5V210 (开发板:QT210) SDRAM: 512M ...

  2. Linux 驱动开发

    linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...

  3. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  4. linux驱动开发流程

    嵌入式linux驱动开发流程嵌入式系统中,操作系统是通过各种驱动程序来驾驭硬件设备的.设备驱动程序是操作系统内核和硬件设备之间的接口,它为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个 ...

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

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

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

    原文网址:http://www.cnblogs.com/xmphoenix/archive/2012/03/27/2420044.html Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书 ...

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

    Linux驱动开发 -- 打开dev_dbg() -- :: 分类: LINUX linux设备驱动调试,我们在内核中看到内核使用dev_dbg来控制输出信息,这个函数的实质是调用printk(KER ...

  8. Linux驱动开发学习的一些必要步骤

      1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ...

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

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

随机推荐

  1. Angular2入门系列教程2-项目初体验-编写自己的第一个组件

    上一篇 使用Angular-cli搭建Angular2开发环境 Angular2采用组件的编写模式,或者说,Angular2必须使用组件编写,没有组件,你甚至不能将Angular2项目启动起来 紧接着 ...

  2. JavaScript性能优化

    如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...

  3. 06.SQLServer性能优化之---数据库级日记监控

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 之前说了一下数据库怎么发邮件:http://www.cnblogs.com/duniti ...

  4. 玩转spring boot——结合jQuery和AngularJs

    在上篇的基础上 准备工作: 修改pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...

  5. 那些年【深入.NET平台和C#编程】

    一.深入.NET框架 1..NET框架具有两个组件:CLR(公共语言运行时)和FCL(框架类库),CLR是.NET框架的基础 2.框架核心类库: System.Collections.Generic: ...

  6. 将DataTable中的某列转换成数组或者List

    string[] arrRate = dtRate.AsEnumerable().Select(d => d.Field<string>("arry")).ToA ...

  7. 【转】java通用URL接口地址调用方式GET和POST方式

    java通用URL接口地址调用方式GET和POST方式,包括建立请求和设置请求头部信息等等......... import java.io.ByteArrayOutputStream; import ...

  8. 文件随机读写专用类——RandomAccessFile

     RandomAccessFile类可以随机读取文件,但是在测试中并不好用;File类可以测试文件存不存在,不存在可以创建文件;FileWriter类可以对文件进行重写或者追加内容;FileReade ...

  9. AspNetPager分页控件样式的使用

    分页是Web应用程序中最常用到的功能之一,AspNetPager  简单实用,应用到项目后台中,棒极了! 自定义样式: <style type="text/css"> ...

  10. SQL面试笔试经典题(Part 1)

    本文是在Cat Qi的原贴的基础之上,经本人逐题分别在MySql数据库中实现的笔记,持续更新... 参考原贴:http://www.cnblogs.com/qixuejia/p/3637735.htm ...