在linux 中,内核打印语句 printk() 会将内核信息输出到内核信息缓冲区中。内核信息缓冲区是一个环形缓冲区(ring buffer),因此,如果插入的信息过多,就会将之前的信息冲刷掉。

printk() 定义了8个消息级别,分为级别0 ~ 7,级别越低(数值越大)的消息越不重要,第0级是紧急事件,

第7级是调试级,在内核中 include/linux/printk.h 中的定义如下:

#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    */

0级,代表紧急事件,一般是系统崩溃之前提示的消息
1级,必须立即采取行动
2级,临界状态,通常涉及严重的硬件或软件操作失败
3级,用于报告错误状态,设备驱动程序会经常使用KERN_ERR 报告来自硬件的问题
4级,对可能出现问题的情况进行警告,这类情况通常不会对系统造成严重问题
5级,有必要进行提示的正常情况,许多与安全相关的状况用这个级别进行提示
6级,内核提示性信息,很多驱动程序在启动的时候用这个级别打印出它们找到的硬件信息
7级,用于调试信息

调试时,通常使用封装了 printk 的更高级的宏,其中可替代 printk 的宏如下:

#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 pr_cont(fmt, ...) \
    printk(KERN_CONT fmt, ##__VA_ARGS__)

/* pr_devel() should produce zero code unless DEBUG is defined */
#ifdef DEBUG
#define pr_devel(fmt, ...) \
    printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_devel(fmt, ...) \
    no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

在打印信息时,如果要打印所出其所在函数,可以使用 __FUNCTION__,

printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION, irq, devname);

对于做Linux内核开发的人来说,printk实在是再熟悉不过了。内核启动时显示的各种信息大部分都是通过她来实现的,在做内核驱动调试的时候大部分 时候使用她就足矣。她之所以用得如此广泛,一个是由于她使用方便,还有一个重要的原因是她的健壮性。它使用范围很广,几乎是内核的任何地方都能调用它。你既可以在中断上下文、进程上下中调用她,也可以在任何持有锁时调用她,更可以在SMP系统中调用她,且调用时连锁都不必使用。这样好的适应性来源于她的设计,一个由三个指针控制的简单“ring buffer”。

注意上面说到的是:“几乎”在内核的任何地方都可以使用。那什么地方使用会有“问题”?那就是在系统启动过程的早期,终端初始化之前的某些地方虽然可以使用,但是在终端和控制台被初始化之前所有信息都被缓存在printk的简单的ring buffer(环形缓冲区)中,直到终端和控制台被初始化之后,所有缓存信息都被一并输出。

如果你要调试的是启动过程最开始的部分(如setup_arch()),可以依靠此时能够工作的硬件设备(如串口)与外界通信,使用printk()的变体early_printk()函数。她在启动过程初期就具有在终端上打印的能力,功能与prink()类似,区别在于:

(1)函数名
(2)能够更早地工作(输出信息)
(3)她有自己的小缓存(一般为512B)
(4)一次性输出到硬件设备,不再以ring buffer的形式保留信息。
但该函数在一些构架上无法实现,所以这种办法缺少可移植性。(大多数构架都可以,包括x86和arm)。
所以,除非要在启动初期在终端上输出,否则我们认为printk()在任何情况下都能工作。这点从内核的启动代码中就可以看出,在已进入start_kernel不久就通过printk打印内核版本信息了。

linux 内核 printk 使用相关推荐

  1. linux内核printk调试

    linux内核printk调试(摘录<Linux安全体系分析与编程>) 1  printk及控制台的日志级别 函数printk的使用方法和printf相似,用于内核打印消息.printk根 ...

  2. Linux 内核 printk打印

    调整内核打印信息级别: cat  /proc/sys/kernel/printk 7       7       1       7          其中第一个"7"表示内核打印 ...

  3. linux内核 printk实现,Linux内核调试技术之printk

    1.简介(基于s3c2440 linux) 在内核调试技术之中,最简单的就是printk的使用了,它的用法和C语言应用程序中的printf使用类似,在应用程序中依靠的是stdio.h中的库,而在lin ...

  4. linux内核printk调试手段,[Mini2440] 内核调试手段之 printk

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 一. 内核打印函数 printk 介绍 1.1 前言 内核提供了 printk 函数在内核运行时打印信息,类似于 C 语 ...

  5. linux内核printk调试手段,linux内核printk调试

    通过printk打你希望追踪的消息.从它的名字可以看出,这个东西有点类似与gnu c中的printf.不过用于内核的东西总该有些特色,printk添加了一些日志级别(loglevel),具体日志级别定 ...

  6. Linux内核printk宏开关

    在内核开发时经常使用printk打印调试信息,但是printk又对性能有一定的影响,比如写了一个驱动调试完毕要发布或者做内核实验调试完毕正式测试时将这些printk删除又很麻烦,之后再想调试又要重新添 ...

  7. linux安全体系分析与编程pdf下载,linux内核printk调试(摘录《Linux安全体系分析与编程》)...

    asmlinkage long sys_syslog(int type, char __user * buf, int len) { return do_syslog(type, buf, len); ...

  8. linux 内核printk 打印信息查询方法

    方法1.直接在终端查询日志 cat /var/log/messages 方法2.直接在一个终端执行 cat /proc/kmsg 然后打开另一个终端,动态加载驱动,在上一个终端中就能看到驱动中prin ...

  9. linux设置printk打印级别,内核printk打印等级

    为了确认内核打印等级以及prink 参数对打印的分级,在led驱动初始化代码[以及exit出口]加入如下代码. 每次insmod .rmmod led模块时,根据打印等级的设置,得到不同的打印结果: ...

最新文章

  1. 在CentOS 6.6 64bit上编译安装LLVM3.7,Clang,Libc++和libc++abi
  2. 安卓SurfaceFlinger框架初探
  3. 【并发编程】Atomic与CAS
  4. pyrMeanShiftFiltering函数
  5. Laravel3 学习笔记
  6. 欢迎各位小伙伴们关注我的公众号,可以随时跟我在微信上进行交流
  7. scala 隐式参数入门及应用
  8. 拓端tecdat|R语言区间数据回归分析
  9. linux内核奇遇记之md源代码解读之五
  10. python类的继承举例_python类的继承实例详解
  11. centos7 redis 重启_linux下redis启动/关闭/重启服务配置
  12. linux 打包大文件,tar打包处理大文件的解压缩方法
  13. 詹森不等式到底是什么?
  14. 成都盛铭轩:电商图片必备哪些信息
  15. python处理word文档 查找文字 加下划线_你能用Pythondocx在同一段落的某一部分加下划线吗?...
  16. [spfa] Jzoj P4722 跳楼机
  17. 如何在eclipse配置服务器server (java ee)
  18. Win 10 运行软件报‘MSCOMCTL.OCX‘缺失怎么办
  19. 未名企鹅极客 | Kylin Cube构建优化(上)
  20. 换位思考:大学教育我之见

热门文章

  1. Linux操作系统Ubuntu部署Oracle篇
  2. Linux驱动编程中EXPORT_SYMBOL()介绍
  3. explain 之 select_type
  4. 关于spring cloud 各种组件的停更/升级/替换
  5. 计算机组成原理——概述2
  6. Mac 技术篇-应用程序被锁定无法进行卸载问题解决方法,文件、文件夹被锁定无法移入废纸篓处理方法,卡巴斯基被锁定如何进行卸载演示
  7. 调试笔记--keil 断点调试小技巧
  8. SDUT_2122 数据结构实验之链表七:单链表中重复元素的删除
  9. 1.7 matlab矩阵元素的引用(可通过下标和序号引用)
  10. Python dataframe修改列顺序(pandas学习)