第十八章 调试git
调试工做艰难是内核级开发区别于用户级开发的一个显著特色。算法
1、准备开始架构
一、内和调试须要什么函数
若是错误老是可以重现的话,消除错误的机会会很大。oop
2、内核中的bug性能
bug发做时可能的症状:学习
3、经过打印来调试测试
printk()就是内核的格式化打印函数ui
一、健壮性spa
健壮性是printk()函数最容易让人们接受的一个特质。任什么时候候,任何地方都能调用它,内核中的printk()比比皆是。
负责执行硬件体系结构相关的初始化动做的函数是:setup_arch()
二、日志等级
printk()和printf()在使用上最主要的区别就是前者能够指定一个日志级别。
内核根据这个级别来判断是否在终端上打印消息。
内核把级别比某个特定值低的全部消息显示在终端上。
可供使用的记录等级:
默认等级:KERN_WARNING
三、记录缓冲区
环形队列的优缺点:
优势:
缺点:
四、syslogd和klogd
4、oops
oops是内核告知用户有不行法神最经常使用的方式。
oops中包含的重要信息对于全部体系结构都是彻底相同的:寄存器上下文和回溯线索。
是一个通过解码的oops,由于内存地址都已经装换成了对应的函数。
一、ksymoops
回溯线索中的地址须要转化成有意义的符号名称才方便使用,这须要调用ksymoops命令。而且还必须提供编译内核时产生的System.map。若是使用的是模块,还须要一些模块信息。
而后该程序就会吐出解码版的oops。若是ksymoops没法找到默认位置上的信息,或者想提供不一样信息,该程序能够接受许多参数。
二、kallsyms
配置选项CONFIG_KALLSYMS_ALL 表示不只存放函数名称,还存放全部的符号名称。
5、内核调试配置选项
6、引起bug并打印信息
一些内核调用能够用来方便标记bug方便标记bug提供断言并输出信息。
最经常使用的两个是BUG()和些声明BUG_ON()。当被调用的时候,它们会引起oops,致使栈的回溯和错误信息的打印。
7、神奇的系统请求键
启用这个键的功能有2个方法:
开启内核编译选项 : CONFIG_MAGIC_SYSRQ
动态启用: echo 1 > /proc/sys/kernel/sysrq
支持sysrq的命令:
8、内核调试器的传奇
一、gdb
二、kgdb
kgdb是一个补丁,它可让咱们在远端主机上经过串口利用gdb的全部功能对内核进行调试。
这须要两台计算机:第一台运行带有kgdb补丁的内核,第二台经过串行线使用gdb对第一台进行调试。
经过kgdb的全部功能都能使用:读取或修改变量值,设置断点,设置关注变量,单步执行等。某些版本的gdb甚至容许执行函数。
9、探测系统
若是对内核调试有丰富的经验的话,那么你会掌握一些诀窍来帮助你更进一步地探测系统从而找到想要的答案。内核调试颇有挑战性,即便是一点小的暗示或者技巧都能给你很大的帮助咱们最好把它们联系起来。
一、用UID做为选择条件
能够利用把用户id做为选择条件来实现这种功能,经过这种选择条件,能够安排到底执行哪一种算法。
if (current->uid != 7777) {
/* 老算法 */
} else {
/* 新算法 */
}
二、使用条件变量
三、使用统计量
当须要掌握某个特定事件的发生规律而且须要比较多个事件并从中得出规律能够经过建立统计量并提供某种机制访问其统计结果。
四、重复频率限制
10、使用Git进行二分搜索
若是你使用Git来控制Linux源码树的副本,那么Git将自动运行二分搜索进程。
Git会在修订版本中进行二分搜索,这样能够找到具体哪次提交的代码引起了bug。
11、小结
这一章讲的是内核的调试。咱们学习了几种技术:内核内置的调试架构、调试程序、记录日志、git二分法查找等。咱们知道了内和调试须要什么一个bug(大部分bug一般都不是行为可靠并且定义明确的)、一个藏匿bug的内核版本(知道bug最先出如今哪一个内核版本中)、相关内核代码的知识和运气(加深理解周围的代码)。以及内核中的bug可能发生的症状等相关问题。