调试

Posted Hawken

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调试相关的知识,希望对你有一定的参考价值。

第十八章调试

18.1 准备开始

         需要准备的东西:

l  一个bug:大部分bug通常都不是行为可靠而且定义明确的

l  一个藏匿bug的内核版本:找出bug首先出现的版本

l  相关内核代码的知识和运气

最好能让bug重现,有一些bug存在而且有人没办法让他重现,因为内核与用户程序和硬件间的交互很微妙。

 

18.2内核中的bug

         可以有无数种原因产生,表象也变化多端。代码中的错误往往引发一系列连锁反应,目击者才看到bug。

 

18.3通过打印来调试

内核提供了打印函数printk()。和C库中的printf()几乎相同。

Printk()的特质:

l  健壮性:任何时候,任何地方都可以调用。仅有的不能调用的情况是在终端还没初始化之前。Early_printk()再启动过程初期就可以打印。

l  日志等级:可以在打印的消息的开头加上记录等级,内核通过记录等级和当前终端的记录登记比较,来决定是否打印。最好给消息加记录等级 ,不然就是默认等级KERN_WARNING。<0>到<7>。

l  记录缓冲区:内核消息保存在一个环形队列中,单处理器默认16k,环形可以新信息覆盖老信息。好处是同步问题容易解决,记录也容易维护。坏处是可能会丢失信息。

l  Syslogd和klogd:用户空间的守护进程klogd从记录缓冲区中获取内核消息,再通过syslogd守护进程将它们保存在系统日志。

l  Printf()到printk():等啥时候写C语言会把pringf()错写成printk()就行了。

 

18.4opps

Oops:是内核告知用户有不幸发生的最常用方式。因为内核不能自我修复,也不能将自己杀死,所以只有发oops。通常发完oops,内核会处于不稳定状态。内核必须适当的从当前上下文环境退出并尝试恢复对系统的控制,但一般会死机。寄存器上下文和回溯线索。

l  Ksymoops:解析opps信息。Ksymoops save_oops.txt

l  Kallsyms:解码不需要再使用system.map和ksymoops工具了

 

18.5 内核调试配置选项

         为了方便调试和测试内核代码,内核提供了配置选项。可以启用slab layer debugging,high-memory debugging,I/O mapping debugging,spin-lock debugging,stack-overflow checking.其中最有用的是sleep-inside-spinlock check

.

18.6引发bug并打印信息

         一些内核调用可以用来方便标记bug,BUG(),BUG_ON()

         Panic()可以引发更严重的错误。dumo_stack()仅在终端上打印寄存器上下文和跟踪线索。

 

18.7神奇的系统请求键

         Sysrq(系统请求)键是救命稻草,无论内核出于什么状态,都可以和内核进行通信。

         Sysrq-h:获取一份可用选项列表

         Sysrq-s:将脏缓冲区跟硬盘交换分区同步

         Sysrq-u:卸载所有的文件系统

Sysrq-b:重启设备

 

18.8内核调试器的传奇

         Gdb:gdb vmlinux /proc/kcore启动调试器。Gdb不能修改内核数据,不能设断点。

         Kgdb:一个补丁,让我们在远端主机上通过串口利用gdb的所有功能得内核进行调试。

 

18.9探测系统

         用UID作为选择条件

         使用条件变量

         使用统计量

         重复频率限制

 

18.10用二分法找出引发罪恶的变更

         知道bug是什么版中出现的,就可以对比没有bug的版本,找出引发bug的代码变更。用二分法找到两个相继版本,一个有bug,一个没bug

 

18.11使用Git进行二分搜索

         Git源码管理工具提供二分搜索机制

以上是关于调试的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核设计与实现 第十八章

Linux内核设计与实现读书笔记——第十八章

linux内核设计与实现一书阅读整理 之第十八章

《linux内核设计与实现》读书笔记第十八章

第十八章 springboot + thymeleaf

第十八章 JDBC