linux设备驱动学习笔记--内核调试方法之printk
1,printk类似于用户态的printf函数,但是比printf函数多了一个日志级别,内核中最常见的日志输出都是通过调用printk来实现的,其打印级别有8种可能的记录字串, 在头文件 <Linux/kernel.h> 里定义:
- KERN_EMERG 0用于紧急消息, 常常是那些崩溃前的消息.
- KERN_ALERT 1需要立刻动作的情形.
- KERN_CRIT 2严重情况, 常常与严重的硬件或者软件失效有关.
- KERN_ERR 3用来报告错误情况; 设备驱动常常使用KERN_ERR 来报告硬件故障.
- KERN_WARNING 4有问题的情况的警告, 这些情况自己不会引起系统的严重问题.
- KERN_NOTICE 5正常情况, 但是仍然值得注意. 在这个级别一些安全相关的情况会报告.
- KERN_INFO 6信息型消息. 在这个级别, 很多驱动在启动时打印它们发现的硬件的信息.
- KERN_DEBUG 7用作调试消息.
2,信息格式化与printf一致,可以有以下几种用法:
- If variable is of Type, useprintk format specifier:
- int %d or %x
- unsignedint %u or %x
- long %ld or %lx
- unsignedlong %lu or %lx
- longlong %lld or %llx
- unsignedlong long %llu or %llx
- size_t %zu or %zx
- ssize_t %zd or %zx
- pointer %p
3,内核有的代码执行很快,如果直接用printk打印会导致系统慢或者卡死现象,内核提供了一个日志流控函数printk_ratelimit,定义及使用如下:
- int printk_ratelimit(void);
- if (printk_ratelimit())
- printk(KERN_INFO“testprint rate limit.\n”);
4,内核中为了方便打印设备编号提供了以下两个函数:
- int print_dev_t(char *buffer, dev_t dev);
- char *format_dev_t(char *buffer, dev_t dev);
定义见内核代码(include\linux\kdev_t.h):
- #define print_dev_t(buffer, dev) \
- sprintf((buffer),"%u:%u\n", MAJOR(dev), MINOR(dev))
- #define format_dev_t(buffer, dev) \
- ({ \
- sprintf(buffer,"%u:%u", MAJOR(dev), MINOR(dev)); \
- buffer; \
- })
5,在linux系统中通过文件/proc/sys/kernel/printk文件可以查看、修改内核的日志级别,此文件有四个数值,分别表示:当前记录级别, 适用没有明确记录级别的消息的缺省级别,允许的最小记录级别, 以及启动时缺省记录级别。例如
- [root@bogon ~]# cat/proc/sys/kernel/printk
- 4 4 1 7
- [root@bogon ~]#
6,不仅可以控制内核的日志级别,还可以通过下面两个文件来控制控制内核通过printk打印的速度。/proc/sys/kernel/{printk_ratelimit ,printk_ratelimit_burst},对应内核代码:
内核对/proc/sys下面的文件会统一导出,其定义在struct ctl_table kern_table[]中:
- {
- .procname = "printk_ratelimit",
- .data =&printk_ratelimit_state.interval, //表示printk_ratelimit文件对应interval值
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec_jiffies,
- },
- {
- .procname = "printk_ratelimit_burst",
- .data =&printk_ratelimit_state.burst, //<span style="font-family: Arial, Helvetica, sans-serif;">表示printk_ratelimit文件对应burst值</span>
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },</span>
流控函数printk_ratelimit()的定义在include\linux\printk.h中,
- #define printk_ratelimit() __printk_ratelimit(__func__)
__printk_ratelimit()函数定义在include\linux\printk.c中
- int __printk_ratelimit(const char *func)
- {
- return ___ratelimit(&printk_ratelimit_state, func);
- }
- EXPORT_SYMBOL(__printk_ratelimit);
最终调用到函数__ratelimit,此函数在lib\ratelimit.c中实现,从实现中可以看出interval控制时间长度,burst控制打印的条数,即调用printk_ratelimit的结果是:在/proc/sys/kernel/printk_ratelimit对应的时间段内(单位秒),打印不超过/proc/sys/kernel/printk_ratelimit_burst对应的条数。
- int ___ratelimit(struct ratelimit_state*rs, const char *func)
- {
- unsignedlong flags;
- intret;
- if(!rs->interval) //从上面可以这个就对应/proc下面的print_ratelimit文件的值
- return1;
- /*
- * If we contend on this state's lock thenalmost
- * by definition we are too busy to print amessage,
- * in addition to the one that will be printedby
- * the entity that is holding the lock already:
- */
- if(!raw_spin_trylock_irqsave(&rs->lock, flags))
- return0;
- if(!rs->begin)
- rs->begin= jiffies;
- if(time_is_before_jiffies(rs->begin + rs->interval)) {
- if(rs->missed)
- printk(KERN_WARNING"%s: %d callbacks suppressed\n",
- func,rs->missed);
- rs->begin = 0;
- rs->printed= 0;
- rs->missed = 0;
- }
- if(rs->burst && rs->burst > rs->printed) { //对应前面的proc文件中print_ratelimit_burst文件的值
- rs->printed++;
- ret= 1;
- }else {
- rs->missed++;
- ret= 0;
- }
- raw_spin_unlock_irqrestore(&rs->lock,flags);
- return ret;
- }
- http://blog.csdn.net/itsenlin/article/details/43205983
linux设备驱动学习笔记--内核调试方法之printk的更多相关文章
- Linux设备驱动学习笔记
之前研究Linux设备驱动时做的零零散散的笔记,整理出来,方便以后复习. 1.1驱动程序的的角色 提供机制 例如:unix图形界面分为X服务器和窗口会话管理器 X服务器理解硬件及提供统一的接口给用户程 ...
- linux设备驱动学习笔记(1)
学习了将近半个月的设备驱动程序的编写,也有一些体会,这里写下来也给学习做一个总结,为后面的学习做更好的准备. 首先,个人感觉驱动程序的设计是很有套路的,最基本的要求就是要掌握这些套路.所谓的套路就是一 ...
- linux字符设备驱动学习笔记(一):简单的字符设备驱动
最近在鼓捣lnux字符设备驱动,在网上搜集的各种关于linux设备驱动的代码和注释,要么是针对2.4的,要么是错误百出,根本就不能运行成功,真希望大家在发博客的时候能认真核对下代码的正确性,特别是要把 ...
- Linux设备驱动开发基础--内核定时器
1. Linux内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 <Linux/timer.h> 和 kernel/timer.c 文件 ...
- 精通linux设备驱动开发 笔记
3.2.7 错误处理 #include <linux/err.h> char * collect_data(char *userbuffer) { char *buffer; /* ...
- linux设备驱动归纳总结(一)内核的相关基础概念【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-59413.html linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxx ...
- 转:Linux设备驱动开发(1):内核基础概念
一.linux设备驱动的作用 内核:用于管理软硬件资源,并提供运行环境.如分配4G虚拟空间等. linux设备驱动:是连接硬件和内核之间的桥梁. linux系统按个人理解可按下划分: 应用层:包括PO ...
- 【Linux开发】linux设备驱动归纳总结(一):内核的相关基础概念
linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
- linux设备驱动概述,王明学learn
linux设备驱动学习-1 本章节主要学习有操作系统的设备驱动和无操作系统设备驱动的区别,以及对操作系统和设备驱动关系的认识. 一.设备驱动的作用 对设备驱动最通俗的解释就是“驱使硬件设备行动” .设 ...
随机推荐
- python实现获取文件夹中的最新文件
实现代码如下: #查找某目录中的最新文件import osclass FindNewFile: def find_NewFile(self,path): #获取文件夹中的所有文件 lists = os ...
- 【NOIP2017】列队【可持久化线段树】
题目链接 题目描述 Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×mn×m名学生,方阵的行数为 n ...
- Win10.设置(放大)
1.ZC:我从感觉,我在Win10 里面截图 貌似被放大了,尤其是 在往cnblogs里面贴图的时候 比较明显,于是 度娘“Win10 自动放大”,找到如下帖子,里面有 2种设置方式: win10系 ...
- 认识requests库,以及安装方法
1.学习requests库有什么意义 1)对我来说,我是测试人员,我用它来解决HTTP接口自动化测试 2)写爬虫需要用到requests 3)如果是开发人员,需要些接口,了解requests有助于掌握 ...
- [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)
[51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...
- 【JAVA】毕向东Java基础视频教程-笔记
传智播客-毕向东Java基础视频教程 <2013年-33days>版-学习代码记录 链接: GitHub库:JavaBXD33 目录 01-Java基础知识 02-Java对象细节 03- ...
- ASE Alpha Sprint - backend scrum 6
本次scrum于2019.11.11在sky garden进行,持续30分钟. 参与人: Zhikai Chen, Jia Ning, Hao Wang 请假: Xin Kang, Lihao Ran ...
- Failed to load C:\ProgramFilesTwo\Android\sdk\build-tools\27.0.3\lib\dx.jar
Eclipse遇到如下错误: Failed to load C:\ProgramFilesTwo\Android\sdk\build-tools\27.0.3\lib\dx.jar 原因: eclip ...
- windows安装 阿里云的Fun工具
由于项目使用到了 函数计算,特此了解到了需要安装 阿里云的Fun工具 Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算.API 网关.日志服务等资源.它通过一个 ...
- AES加密的C语言实现
摘自网上一种AES加密,用C语言实现通过32字节密钥对16字节长度数据进行加密. #include <string.h> #include <stdio.h> #ifndef ...