第十八章调试linux
18.1 准备开始app
一个bug:大部分bug一般都不是行为可靠并且定义明确的ide
一个藏匿bug的内核版本:找出bug首先出现的版本工具
相关内核代码的知识和运气oop
18.2内核中的bug测试
能够有无数种缘由产生,表象也变化无穷。代码中的错误每每引起一系列连锁反应,目睹者才看到bug。spa
18.3经过打印来调试debug
Printk()的特质:调试
健壮性:任什么时候候,任何地方均可以调用。仅有的不能调用的状况是在终端还没初始化以前。Early_printk()再启动过程初期就能够打印。日志
日志等级:能够在打印的消息的开头加上记录等级,内核经过记录等级和当前终端的记录登记比较,来决定是否打印。最好给消息加记录等级 ,否则就是默认等级KERN_WARNING。<0>到<7>。
记录缓冲区:内核消息保存在一个环形队列中,单处理器默认16k,环形能够新信息覆盖老信息。好处是同步问题容易解决,记录也容易维护。坏处是可能会丢失信息。
Syslogd和klogd:用户空间的守护进程klogd从记录缓冲区中获取内核消息,再经过syslogd守护进程将它们保存在系统日志。
Printf()到printk():等啥时候写C语言会把pringf()错写成printk()就好了。
18.4opps
是内核告知用户有不幸发生的最经常使用方式。由于内核不能自我修复,也不能将本身杀死,因此只有发oops。一般发完oops,内核会处于不稳定状态。内核必须适当的从当前上下文环境退出并尝试恢复对系统的控制,但通常会死机。寄存器上下文和回溯线索。
Ksymoops:解析opps信息。Ksymoops save_oops.txt
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源码管理工具提供二分搜索机制
小结: 本章讨论了内核的调试——调试过程其实就是实现与目标误差的行为。