Linux内核(14) - 二分法与printk
人生就是一个茶几,上面摆满了杯具。内核也是一个大茶几,不过它上面的杯具是一个个的bug。确定bug什么时候被引入是一个很关键的步骤,在这个定位bug的过程中,不论有意或无意,都会很自然地用到二分查找的方法。
二分查找法的基本原理
对于二分查找法,我们不会也不应该会感到陌生。作为一种高效的查找算法,它曾出现在我们的数据结构课堂里,出现在一次又一次的面试里,更是会频繁地应用在我们的代码里。在我们所接触到的各种算法里,它可以说是最为大众化、最充满生活智慧的一个,很多人并不知道二分查找法的概念,却能够在生活中熟练的去应用。
比如,一个工人要维修一条10km长的电话线,首先他需要定位出故障所在,如果沿着线路一小段一小段地查找,显然非常得困难,每查一个点都要爬一次电线杆,10km长的距离会有大约200多根电线杆。假设电线两端分别为A、B,这时他会很自然地首先从中间的C开始查起,用话机向两端测试时,发现AC段正常,故而断定故障在BC段,再到BC段的中点D,如果发现BD段正常,则故障在CD段,然后再到CD的中间点E查找,这样每查一次,就可以把待查线路的长度缩减一半,因而经过7次查找,就可以将故障发生的范围缩小到50~100m左右,即在一两根电线杆附近。如此一来要节省很多的精力与时间。
这是二分查找法在生活中的一个典型应用,实际上,查找内核的bug与查找电话线的故障相比,本质上都是相同的,并没有高深到哪里去,都是首先要定位出故障的位置,然后去解决它。
比如你在使用某个版本的内核时,发现了一个内核bug,这时你需要知道它究竟是在应用哪个补丁时被引入的,如果一个一个的去还原那些补丁,每还原一个补丁就要测试一次内核,那么必然会浪费过多的时间,而应用二分查找法,首先确定一个肯定没有出现该bug的内核版本,然后去测试位于这两个版本中间的那个版本,这样重复筛选,就能够很容易的定位出是从哪个版本开始出现了这个bug。
printk()
printk()应该是每一个驱动开发者最为亲密的伙伴了,我们常常将它与二分查找法结合在一起寻找代码中发生问题的位置。
通常情况下,对于代码中的两个printk()语句,如果一个正常执行,而另一个没有被执行,就说明问题发生在这两个printk()之间,接下来就可以在这个范围内应用二分查找法定位有问题的代码。
1. printk()与printf()
用户空间有printf(),内核空间有printk(),它们就如代表善与恶的命运双生子,即使长相功能如何的接近,都不能在代码中共存。
对于我们来说,最容易犯的错误是,在需要printk()的地方误用了printf(),而在需要printf()的地方却又误用了printk(),通常这都不会是因为不知道它们的区别,而只是习惯使然。民间流传有这样的说法:当你在编写用户空间应用程序的时候,下意识写出的都是printk(),那么就说明你是个标准的内核开发者了。
2. printk()的消息级别
printk()与printf()的一个重要区别就是前者可以指定消息的打印级别,内核根据这个指定的级别来决定是否将消息打印到终端上。如下表所示,printk()共有8个级别。
级别 |
描述 |
KERN_EMERG |
紧急情况,系统可能会崩溃 |
KERN_ALERT |
必须立即响应 |
KERN_CRIT |
临界情况 |
KERN_ERR |
错误信息 |
KERN_WARNING |
警告信息 |
KERN_NOTICE |
普通的但可能需要注意的信息 |
KERN_INFO |
提示性信息 |
KERN_DEBUG |
调试信息 |
如果没有指定消息的级别,printk()会使用默认的DEFAULT_MESSAGE_LOGLEVEL(通常是KERN_WARNING)。
3. 控制台的日志级别(console_loglevel)
当printk指定的消息级别小于指定的控制台日志级别时,消息的内容就会显示在该控制台上。控制台的日志级别定义在include/linux/kernel.h文件中,默认为DEFAULT_CONSOLE_LOGLEVEL(值等于7),也就是说默认情况下,比KERN_DEBUG级别高的printk()消息内容都可以在控制台上显示。
我们可以执行下面的命令使任何级别的printk()消息都被打印在终端上
$ echo 8 > /proc/sys/kernel/printk
4. printk()的变体
内核在include/linux/kernel.h文件中提供了两个printk()的变体pr_debug和pr_info,它们的定义为:
235 #define pr_debug(fmt,arg...) /
236 printk(KERN_DEBUG fmt,##arg)
244 #define pr_info(fmt,arg...) /
245 printk(KERN_INFO fmt,##arg)
5. printk()不是万能的
printk()虽然很好用,但它并不是万能的,在系统启动时,终端还没有初始化之前,它并不能被使用,不过如果不是在调试系统的启动过程的话,这并不能算是个问题。
其实内核提供了一个printk()的变体early_printk(),专门用于在系统启动的初期在终端上打印消息,它与printk()的区别仅仅在于名字的不同以及它能够更早地工作。
Linux内核(14) - 二分法与printk的更多相关文章
- linux内核调试技术之printk
原创博客:欢迎转载,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=6218383 1.简介(基于s3c2440 linux) 在内核调试技术之中 ...
- Linux内核调试的方式以及工具集锦【转】
转自:https://blog.csdn.net/gatieme/article/details/68948080 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...
- Linux内核调试的方式以及工具集锦
原文:https://blog.csdn.net/gatieme/article/details/68948080 CSDN GitHubLinux内核调试的方式以及工具集锦 LDD-LinuxDev ...
- linux内核打印数据到串口控制台,printk数据不打印问题
linux内核打印数据到串口控制台问题 原文来源:http://i.cnblogs.com/EditPosts.aspx?opt=1 1.查看当前控制台的打印级别 cat /proc/sys/kern ...
- Nginx之旅系列 - Nginx日志功能 PK Linux内核printk
题记:Nginx之旅系列是用来记录Nginx从使用到源码学习的点点滴滴,分享学习Nginx的快乐 Nginx 首页: http://nginx.org/ Nginx日志功能 PK Linux内核pri ...
- Linux内核2.6.14源码分析-双向循环链表代码分析(巨详细)
Linux内核源码分析-链表代码分析 分析人:余旭 分析时间:2005年11月17日星期四 11:40:10 AM 雨 温度:10-11度 编号:1-4 类别:准备工作 Email:yuxu97101 ...
- 2018-2019-1 20189215《Linux内核原理与分析》第二周作业
本周学习了<庖丁解牛>第1章,以及<Linux内核设计与实现>第1.2.18章.通过视频和实验,学会了反汇编一个简单的C程序,也学习了Linux内核调试的一些小技巧和print ...
- 初探内核之《Linux内核设计与实现》笔记下
定时器和时间管理 系统中有很多与时间相关的程序(比如定期执行的任务,某一时间执行的任务,推迟一段时间执行的任务),因此,时间的管理对于linux来说非常重要. 主要内容: 系统时间 定时器 定时器相关 ...
- 解析 Linux 内核可装载模块的版本检查机制
转自:http://www.ibm.com/developerworks/cn/linux/l-cn-kernelmodules/ 为保持 Linux 内核的稳定与可持续发展,内核在发展过程中引进了可 ...
随机推荐
- JQuery缓冲加载图片插件lazyload.js的使用方法
lazyload.js是一个基于JQuery的插件,可以用来缓冲加载图片.如果一个网页很长并且有很多图片的话,下载图片就需要很多时间,那么就会影响整个网页的加载速度,而这款延迟加载插件,会通过你的滚动 ...
- 运用CSS改进网站设计的3个技巧
CSS是一种分离表述编码和实际内容的一种最有用的方式,也是一种使搜索引擎最优化的方式,通常,网站设计中会建立一整套的css样式标准,这些标准存储在一个扩展名为css的单独文件中.然后利用HTML标签设 ...
- 模态框在IE下的问题,即position:fixed在IE下不兼容的处理方式
项目中遇到的问题,模态框在IE下总出现如图所示双层遮罩框,经排查发现是由于bootstrap里写的modal的样式里position:fixed不兼容IE的原因,导致铺不满整个窗口. 解决方案:在项目 ...
- 上传文件multipart form-data boundary 说明
含义 ENCTYPE="multipart/form-data" 说明: 通过 http 协议上传文件 rfc1867协议概述,客户端发送内容构造. 概述 ...
- 【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现
Ribbon负载均衡策略定义 IRule其实就只做了一件事情Server choose(Object key),可以看到这个功能是在LB中定义(要求)的,LB把这个功能委托给IRule来实现.不同的I ...
- 图解Eclipse或者SpringSource Tool Suite 创建模块化Maven项目
第一步:Package Explorer里选择右键,新建Maven项目,如果没有在Other里找,还没有确认一下是否安装了Maven插件 第二步:在Wizards向导里可以通过搜索,找到Maven P ...
- nginx rewrite only specific servername to https
需求: 把某个域名的80端口服务 ----> 重定向转到 这个域名的 443端口的服务. server { listen 80; server_name xxx.abcd.com.cn; ...
- 虚拟机配置Cognos报错CFG-ERR-0106
在虚拟机中安装Cognos 之后,启动了好多次,都启动失败,如下图所示,错误如下图所示 已确保已下信息设置正确 1:内容库配置OK 2:Java_home OK 3:字符集OK ----------- ...
- C#类似版本号有多个分割符可以产生的排列组合,类似版本号比较
我采用asp.net进行演示 送给有缘人吧,可以获得类似版本号的功能,也可以对比两个版本号,我这里是其他需要用逗号分割的 using System; public partial class _Def ...
- HDU 2178.猜数字【分析能力练习】【读题能力练习】【8月10】
猜数字 Problem Description A有1数m.B来猜.B每猜一次,A就说"太大"."太小"或"对了" . 问B猜n次能够猜到的 ...