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

摘要:
在头文件<它通常与严重的硬件或软件故障有关。KERN_ ERR 3用于报告错误条件;设备驱动程序通常使用KERN_ERR报告硬件故障。KERN_WARNING 4有关问题的警告,请参阅内核代码(includelinuxkdev_t.h):MINOR(dev))#define format_ dev_ t(buffer,MINOR(dev));
 

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

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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一致,可以有以下几种用法:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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,定义及使用如下:

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. int printk_ratelimit(void);  
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. if (printk_ratelimit())  
  2.     printk(KERN_INFO“testprint rate limit. ”);  

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

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. int print_dev_t(char *buffer, dev_t dev);  
  2. char *format_dev_t(char *buffer, dev_t dev);  


定义见内核代码(includelinuxkdev_t.h):

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. #define print_dev_t(buffer, dev)                   
  2.     sprintf((buffer),"%u:%u ", MAJOR(dev), MINOR(dev))  
  3.    
  4. #define format_dev_t(buffer, dev)                  
  5.     ({                            
  6.        sprintf(buffer,"%u:%u", MAJOR(dev), MINOR(dev));      
  7.        buffer;                           
  8.     })  

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

 

[plain] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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[]中:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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.   
  12.            .maxlen             = sizeof(int),  
  13.            .mode                = 0644,  
  14.            .proc_handler  = proc_dointvec,  
  15.  },</span>  

流控函数printk_ratelimit()的定义在includelinuxprintk.h中,

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. #define printk_ratelimit()  __printk_ratelimit(__func__)  

__printk_ratelimit()函数定义在includelinuxprintk.c中
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. int __printk_ratelimit(const char *func)  
  2. {  
  3.     return ___ratelimit(&printk_ratelimit_state, func);  
  4. }  
  5. EXPORT_SYMBOL(__printk_ratelimit);  
最终调用到函数__ratelimit,此函数在lib atelimit.c中实现,从实现中可以看出interval控制时间长度,burst控制打印的条数,即调用printk_ratelimit的结果是:在/proc/sys/kernel/printk_ratelimit对应的时间段内(单位秒),打印不超过/proc/sys/kernel/printk_ratelimit_burst对应的条数。
[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. int ___ratelimit(struct ratelimit_state*rs, const char *func)  
  2. {  
  3.          unsignedlong flags;  
  4.          intret;  
  5.    
  6.          if(!rs->interval)       //从上面可以这个就对应/proc下面的print_ratelimit文件的值  
  7.   
  8.                    return1;  
  9.    
  10.          /*  
  11.           * If we contend on this state's lock thenalmost  
  12.           * by definition we are too busy to print amessage,  
  13.           * in addition to the one that will be printedby  
  14.           * the entity that is holding the lock already:  
  15.           */  
  16.          if(!raw_spin_trylock_irqsave(&rs->lock, flags))  
  17.                    return0;  
  18.    
  19.          if(!rs->begin)  
  20.                    rs->begin= jiffies;  
  21.    
  22.          if(time_is_before_jiffies(rs->begin + rs->interval)) {  
  23.                    if(rs->missed)  
  24.                             printk(KERN_WARNING"%s: %d callbacks suppressed ",  
  25.                                      func,rs->missed);  
  26.                    rs->begin   = 0;  
  27.                    rs->printed= 0;  
  28.                    rs->missed  = 0;  
  29.          }  
  30.          if(rs->burst && rs->burst > rs->printed) {  //对应前面的proc文件中print_ratelimit_burst文件的值  
  31.   
  32.                    rs->printed++;  
  33.                    ret= 1;  
  34.          }else {  
  35.                    rs->missed++;  
  36.                    ret= 0;  
  37.          }  
  38.          raw_spin_unlock_irqrestore(&rs->lock,flags);  
  39.    
  40.          return ret;  
  41. }  
    1. http://blog.csdn.net/itsenlin/article/details/43205983

免责声明:文章转载自《linux设备驱动学习笔记--内核调试方法之printk》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇typro常用快捷键springboot整合amazonS3,封装上传文件接口下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

node rpc 使用

什么是rpc RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务 本地过程调用:如果需要将本地student对象的age+1,可以实现一个addAge()方法,将student对象传入,对年龄进行更新之后返回即可,本地方法调用的函数体通过函数指针来指定。 远程过程调用:上述操作的过程中,如果ad...

XML格式以及相关libxml库学习

本文参考 XML文件格式语法以及DTD,摘除其中自己认为必要的知识点,在此记录如下。 先给出一个xml的实例文件, <?xml version="1.0" encoding="utf-8"?> <gadget> <name>日历</name> <namespace> <...

win10安装mysql5.7.29教程以及错误处理

重新配了一台电脑,装了win10系统,安装mysql是出现了一些问题以及解决的方法。记录于此,避免下次安装遇到重复问题。 首先下载mysql5.7.29安装包,本次使用的是zip。已保存在百度网盘 链接:https://pan.baidu.com/s/1y8aahxloQEJTGXqmd95xsg 提取码:e3c6 也可以自己去官网下载: 下载地址:  h...

python json数据的转换

1  Python数据转json字符串   import json   json_str = json.dumps(py_data) 参数解析:   json_str = json.dumps(py_data,sort_keys=True,indent =4,separators=(',', ': '),encoding="gbk",ensure_asc...

windows下的shellcode剖析浅谈[转自看雪]

标 题: 【原创】windows下的shellcode剖析浅谈作 者:snowdbg时 间: 2009-10-06,11:12链 接: http://bbs.pediy.com/showthread.php?t=99007  今天是中秋节,正好我的文章在今天基本完成,作为中秋礼物送给大家,由于本人水平有限希望大家多多批评指正!学习了好些日子了,思路总是乱...

一步步把 SAP UI5 应用部署到 SAP BTP Kyma 运行环境中去

这是 Jerry 2021 年的第 40 篇文章,也是汪子熙公众号总共第 317 篇原创文章。 Jerry 2018年曾经写过两篇文章,介绍了如何在 Kubernetes 这个容器编排平台上运行一个包含 SAP UI5 应用的 Docker 镜像。 在 Kubernetes 上运行 SAP UI5 应用(上) 在 Kubernetes 上运行 SAP U...