linux设备驱动学习笔记--内核调试方法之printk

时间:2021-10-09 17:56:52

1,printk类似于用户态的printf函数,但是比printf函数多了一个日志级别,内核中最常见的日志输出都是通过调用printk来实现的,其打印级别有8种可能的记录字串, 在头文件 <Linux/kernel.h> 里定义:

  1. KERN_EMERG  0用于紧急消息, 常常是那些崩溃前的消息.
  2. KERN_ALERT  1需要立刻动作的情形.
  3. KERN_CRIT  2严重情况, 常常与严重的硬件或者软件失效有关.
  4. KERN_ERR  3用来报告错误情况; 设备驱动常常使用KERN_ERR 来报告硬件故障.
  5. KERN_WARNING  4有问题的情况的警告, 这些情况自己不会引起系统的严重问题.
  6. KERN_NOTICE  5正常情况, 但是仍然值得注意. 在这个级别一些安全相关的情况会报告.
  7. KERN_INFO  6信息型消息. 在这个级别, 很多驱动在启动时打印它们发现的硬件的信息.
  8. KERN_DEBUG  7用作调试消息.

2,信息格式化与printf一致,可以有以下几种用法:

  1. If variable is of Type,                  useprintk format specifier:
  2. int                                      %d or %x
  3. unsignedint                              %u or %x
  4. long                                     %ld or %lx
  5. unsignedlong                             %lu or %lx
  6. longlong                                 %lld or %llx
  7. unsignedlong long                        %llu or %llx
  8. size_t                                   %zu or %zx
  9. ssize_t                                  %zd or %zx
  10. pointer                                  %p

3,内核有的代码执行很快,如果直接用printk打印会导致系统慢或者卡死现象,内核提供了一个日志流控函数printk_ratelimit,定义及使用如下:

  1. int printk_ratelimit(void);
  1. if (printk_ratelimit())
  2. printk(KERN_INFO“testprint rate limit.\n”);

4,内核中为了方便打印设备编号提供了以下两个函数:

  1. int print_dev_t(char *buffer, dev_t dev);
  2. char *format_dev_t(char *buffer, dev_t dev);

定义见内核代码(include\linux\kdev_t.h):

  1. #define print_dev_t(buffer, dev)                 \
  2. sprintf((buffer),"%u:%u\n", MAJOR(dev), MINOR(dev))
  3. #define format_dev_t(buffer, dev)                \
  4. ({                          \
  5. sprintf(buffer,"%u:%u", MAJOR(dev), MINOR(dev));    \
  6. buffer;                         \
  7. })

5,在linux系统中通过文件/proc/sys/kernel/printk文件可以查看、修改内核的日志级别,此文件有四个数值,分别表示:当前记录级别, 适用没有明确记录级别的消息的缺省级别,允许的最小记录级别, 以及启动时缺省记录级别。例如

  1. [root@bogon ~]# cat/proc/sys/kernel/printk
  2. 4       4      1       7
  3. [root@bogon ~]#

6,不仅可以控制内核的日志级别,还可以通过下面两个文件来控制控制内核通过printk打印的速度。/proc/sys/kernel/{printk_ratelimit ,printk_ratelimit_burst},对应内核代码:

内核对/proc/sys下面的文件会统一导出,其定义在struct ctl_table kern_table[]中:

  1. {
  2. .procname        = "printk_ratelimit",
  3. .data             =&printk_ratelimit_state.interval, //表示printk_ratelimit文件对应interval值
  4. .maxlen             = sizeof(int),
  5. .mode                = 0644,
  6. .proc_handler  = proc_dointvec_jiffies,
  7. },
  8. {
  9. .procname        = "printk_ratelimit_burst",
  10. .data            =&printk_ratelimit_state.burst,  //<span style="font-family: Arial, Helvetica, sans-serif;">表示printk_ratelimit文件对应burst值</span>
  11. .maxlen             = sizeof(int),
  12. .mode                = 0644,
  13. .proc_handler  = proc_dointvec,
  14. },</span>

流控函数printk_ratelimit()的定义在include\linux\printk.h中,

  1. #define printk_ratelimit()  __printk_ratelimit(__func__)

__printk_ratelimit()函数定义在include\linux\printk.c中

  1. int __printk_ratelimit(const char *func)
  2. {
  3. return ___ratelimit(&printk_ratelimit_state, func);
  4. }
  5. EXPORT_SYMBOL(__printk_ratelimit);

最终调用到函数__ratelimit,此函数在lib\ratelimit.c中实现,从实现中可以看出interval控制时间长度,burst控制打印的条数,即调用printk_ratelimit的结果是:在/proc/sys/kernel/printk_ratelimit对应的时间段内(单位秒),打印不超过/proc/sys/kernel/printk_ratelimit_burst对应的条数。

  1. int ___ratelimit(struct ratelimit_state*rs, const char *func)
  2. {
  3. unsignedlong flags;
  4. intret;
  5. if(!rs->interval)       //从上面可以这个就对应/proc下面的print_ratelimit文件的值
  6. return1;
  7. /*
  8. * If we contend on this state's lock thenalmost
  9. * by definition we are too busy to print amessage,
  10. * in addition to the one that will be printedby
  11. * the entity that is holding the lock already:
  12. */
  13. if(!raw_spin_trylock_irqsave(&rs->lock, flags))
  14. return0;
  15. if(!rs->begin)
  16. rs->begin= jiffies;
  17. if(time_is_before_jiffies(rs->begin + rs->interval)) {
  18. if(rs->missed)
  19. printk(KERN_WARNING"%s: %d callbacks suppressed\n",
  20. func,rs->missed);
  21. rs->begin   = 0;
  22. rs->printed= 0;
  23. rs->missed  = 0;
  24. }
  25. if(rs->burst && rs->burst > rs->printed) {  //对应前面的proc文件中print_ratelimit_burst文件的值
  26. rs->printed++;
  27. ret= 1;
  28. }else {
  29. rs->missed++;
  30. ret= 0;
  31. }
  32. raw_spin_unlock_irqrestore(&rs->lock,flags);
  33. return ret;
  34. }  
    1. http://blog.csdn.net/itsenlin/article/details/43205983

linux设备驱动学习笔记--内核调试方法之printk的更多相关文章

  1. Linux设备驱动学习笔记

    之前研究Linux设备驱动时做的零零散散的笔记,整理出来,方便以后复习. 1.1驱动程序的的角色 提供机制 例如:unix图形界面分为X服务器和窗口会话管理器 X服务器理解硬件及提供统一的接口给用户程 ...

  2. linux设备驱动学习笔记(1)

    学习了将近半个月的设备驱动程序的编写,也有一些体会,这里写下来也给学习做一个总结,为后面的学习做更好的准备. 首先,个人感觉驱动程序的设计是很有套路的,最基本的要求就是要掌握这些套路.所谓的套路就是一 ...

  3. linux字符设备驱动学习笔记(一):简单的字符设备驱动

    最近在鼓捣lnux字符设备驱动,在网上搜集的各种关于linux设备驱动的代码和注释,要么是针对2.4的,要么是错误百出,根本就不能运行成功,真希望大家在发博客的时候能认真核对下代码的正确性,特别是要把 ...

  4. Linux设备驱动开发基础--内核定时器

    1. Linux内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 <Linux/timer.h> 和 kernel/timer.c 文件 ...

  5. 精通linux设备驱动开发 笔记

      3.2.7 错误处理   #include <linux/err.h> char * collect_data(char *userbuffer) { char *buffer; /* ...

  6. linux设备驱动归纳总结(一)内核的相关基础概念【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-59413.html linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxx ...

  7. 转:Linux设备驱动开发(1):内核基础概念

    一.linux设备驱动的作用 内核:用于管理软硬件资源,并提供运行环境.如分配4G虚拟空间等. linux设备驱动:是连接硬件和内核之间的桥梁. linux系统按个人理解可按下划分: 应用层:包括PO ...

  8. 【Linux开发】linux设备驱动归纳总结(一):内核的相关基础概念

    linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  9. linux设备驱动概述&comma;王明学learn

    linux设备驱动学习-1 本章节主要学习有操作系统的设备驱动和无操作系统设备驱动的区别,以及对操作系统和设备驱动关系的认识. 一.设备驱动的作用 对设备驱动最通俗的解释就是“驱使硬件设备行动” .设 ...

随机推荐

  1. ecmall中static变量的使用-model模型代码设计

    function &m($model_name, $params = array(), $is_new = false) { static $models = array(); $model_ ...

  2. Openstack&plus;Kubernetes&plus;Docker微服务实践之路--基础设施

    近两年微服务在网上聊的如此的如火如荼,备受关注,我在去年下半年的一个项目中也用到了阿里云的EDAS.HSF,深有体会,最近时间空闲出于好奇,决定一探究竟打算自建微服务平台,基本实现EDAS.HSF的功 ...

  3. 高通CP Crash分析调试

    1. 转换tlcore文件 获取 EBICS0.BIN tl2elf --qconly tlcore 2.使用T32 命令把Riva的dump信息从EBICS0文件分离出来 data.load.BIN ...

  4. HTML中Id和Name的区别

    源地址:http://www.cnblogs.com/laodai/articles/2244215.html 在html中:name指的是用户名称,ID指的是用户注册是系统自动分配给用户的一个序列号 ...

  5. Python处理Excel(转载)

    1. Python 操作 Excel 的函数库 我主要尝试了 3 种读写 Excel 的方法: 1> xlrd, xlwt, xlutils: 这三个库的好处是不需要其它支持,在任何操作系统上都 ...

  6. python爬虫数据解析之BeautifulSoup

    BeautifulSoup是一个可以从HTML或者XML文件中提取数据的python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式. BeautfulSoup是python爬虫三 ...

  7. Linux下批量管理工具pssh安装和使用

    Linux下批量管理工具pssh安装和使用 pssh工具包 安装:yum -y install pssh pssh:在多个主机上并行地运行命令 pscp:把文件并行地复制到多个主机上 prsync:通 ...

  8. &period;Net语言 APP开发平台——Smobiler学习日志:如何设置页面的title

    1.修改Mobile Form的TitleText的属性 输入需要显示标题,如图1: 2.修改Mobile Form的TitleStyle属性 其中包括Image属性(窗体图标).BackColor属 ...

  9. python - beautifulsoup4模块

    # beautifulsoup4学习 # 是一个python模块 用于接受一个HTML 或 XML 字符串,然后将其进行格式化,之后便可以使用模块提供的方法进行快速查找指定元素, # 从而是的在HTM ...

  10. MyEclipse 10&period;7(版本:eclipse 3&period;7&period;x-Indigo系列)安装PyDev 4&period;5&period;4插件

    解压安装路径结构如截图所示: 安装后重启: