Linux内核设计与实现(18)第十八章:内核调试

1. 内核态调试难点

内核调试的难点在于它不能像用户态程序调试那样打断点,随时暂停查看各个变量的状态。
也不能像用户态程序那样崩溃后迅速的重启,恢复初始状态。

内核调试的难点大致有以下几个:

1.重现bug困难
	如果能够重现一个bug, 相当于成功了一半. 
	(特别是有些bug和硬件相关, 执行几百万次之后才有一次错误)
	
2.调试风险比较大
	稍有不慎, 即造成系统崩溃

3.定位bug的初始版本困难
	内核版本更新很快, 很难确定bug是在那个版本开始出现的

1.1 KDB 调试

KDB入门和MIPS汇编
https://blog.csdn.net/lqy971966/article/details/115862769

1.2 解决:

内核出错之后整个系统就无法正常运行了,所以要想熟练的进行内核调试,
首先要熟悉内核已经给我们提供的工具,然后实实在在的去做一些内核功能的开发,在开发的过程中不断熟悉内核代码,增加内核调试的经验。

1.2.1 输出 LOG(printk)

linux内核中输出LOG的函数是 printk (语法和printf几乎雷同, 唯一的区别是printk可以指定日志级别)
printk 之所以好用, 就在与它随时都可以被调用, 没有任何限制条件.

LOG等级
KERN_EMERG KERN_ALERT KERN_CRIT KERN_ERR KERN_WARNING KERN_NOTICE KERN_INFO KERN_DEBUG

输出示例:
printk(KERN_WARNING "This is a warning!\n");
printk(KERN_DEBUG "This is a debug notice!\n");

LOG记录
标准linux系统上, printk 输出log之后, 由用户空间的守护进程klogd从缓冲区中读取内核消息, 然后再通过syslogd守护进程将它们保存在系统日志文件中.
syslogd 将接受到的所有内核消息添加到一个文件中, 该文件默认为: /var/log/dmesg

1.2.2 oops

oopss是个拟声词, 类似 “哎哟” 的意思. 它是内核通知用户有不幸发生的最常用方式.
oops中包含错误发生时的一些重要信息(比如, 寄存器上下文和回溯线索), 对调试bug很有帮助!

1.2.3 主动触发 bug

调试中有时将某些情况下标记为bug, 执行到这些情况时, 提供断言并输出信息.
BUG 和 BUG_ON 就是2个可以主动触发oops的内核调用.

在不应该被执行到的地方使用 BUG 或者 BUG_ON 来捕获.

比如:
if (bad_thing)
	BUG();
// 或者
BUG_ON(bad_thing);

如果想要触发更为严重的错误, 可以使用 panic() 函数
比如:
if (terrible_thing)
	panic("terrible thing is %ld\n", terrible_thing);

此外, 还有 dump_stack 函数可以打印寄存器上下文和回溯信息.
比如:
if (!debug_check) {
	printk(KERN_DEBUG "provide some information...\n");
	dump_stack();
}

1.2.3.1 panic

panic 就是:当系统发现无法继续运行下去的故障时将调用它,会导致程序中止,然后由系统显示错误号

分类:

1.hard panic(也就是Aieee信息输出)
对于hard panic而言,最大的可能性是驱动模块的中断处理(interrupt handler)导致的
	一般出现下面的情况,就认为是发生了 hard panic:
		1.机器彻底被锁定,不能使用
		2.数字键(Num Lock),大写锁定键(Caps Lock),滚动锁定键(Scroll Lock)不停闪烁。
		3.如果在终端下,应该可以看到内核dump出来的信息(包括一段”Aieee”信息或者”Oops”信息)
		4.和Windows蓝屏相似

2.soft panic (也就是Oops信息输出)
	只有加载到内核空间的驱动模块才能直接导致kernel panic

1.2.4 神奇的系统请求键

这个系统请求键之所以神奇, 在于它可以在一个快挂了的系统上输出一些有用的信息.
这个按键一般就是标准键盘上的 [SysRq] 键 (就在 F12 键右边, 其实就是windows中截整个屏幕的按键)
单独按那个键相当于截屏, 按住 ALT + [SysRq] = [SysRq]的功能

启用这个键的功能有2个方法:
开启内核编译选项 : CONFIG_MAGIC_SYSRQ
动态启用: echo 1 > /proc/sys/kernel/sysrq

1.2.5 其他:gdb 和 kdb

内核调试器 gdb和kgdb 探测系统 用UID控制内核执行

通俗易懂说GDB调试(三)总结
https://blog.csdn.net/lqy971966/article/details/103118094

KDB入门和MIPS汇编
https://blog.csdn.net/lqy971966/article/details/115862769

猜你喜欢

转载自blog.csdn.net/lqy971966/article/details/119821812