内核调试

转自http://www.cnblogs.com/wang_yb/p/3504539.html
内核调试的难点在于它不能像用户态程序那样打断点,随时暂停查看各个变量的状态。也不能像用户态程序那样崩溃后迅速的重启,恢复初始状态。
用户态程序和内核交互,用户态程序的各种状态、错误等都可以由内核来捕获并显示。
而内核是直接和硬件交互的,内核出错之后整个系统就无法正常运行了,所以要想熟练地进行内核调试,首先要熟悉内核已经提供给我们的工具,然后实实在在地去做一些内核功能的开发,在开发的过程中不断熟悉内核代码,增加内核调试的经验。

内核调试的难点

  1. 重现bug困难-如果能够重现一个bug,相当于成功了一半。(特别是有些bug和硬件相关,执行几百万次后才有一次错误)
  2. 调试风险比较大-稍有不慎,即造成系统崩溃。
  3. 定位bug的初始版本困难-内核版本更新很快,很难确定bug是在哪个版本开始出现的。

内核调试的工具和方法

输出log

输出log不光是内核调试,即使是在用户态程序的调试中,也是经常使用的一个调试手段。
通过在可以的代码周围加上一些LOG输出,可以准确地了解bug发生前后的一些重要信息。
1.log等级
linux内核中输出LOG的函数是 printk (语法和printf几乎雷同, 唯一的区别是printk可以指定日志级别)
printk之所以好用, 就在与它随时都可以被调用, 没有任何限制条件.
printk的输出日志级别如下:

等级描述
KERN_EMERG一个紧急情况
KERN_AKERT一个需要被立即注意到的错误
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");

2.log记录
标准linux系统上, printk 输出log之后, 由用户空间的守护进程klogd从缓冲区中读取内核消息, 然后再通过syslogd守护进程将它们保存在系统日志文件中.
syslogd 将接受到的所有内核消息添加到一个文件中, 该文件默认为: /var/log/dmesg (系统Centos6.4 x86_64)
PS. 上篇博客中的内核模块的输出LOG, 都可以在 /var/log/dmesg 中看到
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_statck();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值