Linux内核调试手段

常用调试方法:

1、printk()

在内核代码中添加printk()函数用来输出插入调试信息,从而掌握程序执行位置。
printk函数存在输出等级规则:

#defineKERN_EMERG"<0>"    /*紧急事件消息,系统崩溃之前提示,表示系统不可用*/
#defineKERN_ALERT"<1>"    /*报告消息,表示必须立即采取措施*/
#defineKERN_CRIT"<2>"     /*临界条件,通常涉及严重的硬件或软件操作失败*/
#defineKERN_ERR"<3>"      /*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/
#defineKERN_WARNING"<4>"  /*警告条件,对可能出现问题的情况进行警告*/
#defineKERN_NOTICE"<5>"   /*正常但又重要的条件,用于提醒。常用于与安全相关的消息*/
#defineKERN_INFO"<6>"     /*提示信息,如驱动程序启动时,打印硬件信息*/
#defineKERN_DEBUG"<7>"    /*调试级别的消息*/
 printk(KERN_INFO "hello world!/n");

printk内核最经常使用的打印函数,它的使用方法和用户空间的printf函数一样。稍微不同的是,printk可以通过参数指定打印等级,对应的控制台也有打印等级,只有优先级高于控制台的printk打印才会显示到屏幕上,低优先级的打印都会被过滤掉。
控制台的打印等级:

# 查看控制台的打印等级命令
$: cat /proc/sys/kernel/printk
7	4	1	7

如上输出的4个数字意义为:
1、 控制台打印等级:优先级高于该值的printk打印才会输出到控制台重定向的串口或屏幕上
2、默认的消息日志级别
3、最低的控制台日志级别
4、默认的控制台日志级别
数字越小,优先级越高。内核默认的printk打印等级是4,高于控制台的打印优先级7,所以在内核模块中使用printk打印,都可以在屏幕上看到输出的。如果我们将控制台打印等级修改为3,就看不到内核模块的打印信息。

2、dump_stack()

dump_stack()函数是常用的函数调用栈打印函数,该函数可以将某个指定函数的上下文调用关系打印出来,由此可以快速的分析内核源码的调用过程。
使用例程:

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ImagineMiracle");

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello world\n");
    dump_stack();
    return 0;
}
static void __exit hello_exit(void)
{
    printk("Bye world\n");
}
module_init(hello_init);
module_exit(hello_exit);

在hello内核模块的hello_init函数内添加dump_stack(),当使用isnmod加载模块到内核执行,调用hello_init函数时,就会打印其所在函数的调用关系。

[root@linux]# insmod hello.ko 
[ 3543.891700] Hello world
[ 3543.892289] CPU: 0 PID: 181 Comm: insmod Tainted: G           O      5.10.0-rc3+ #10
[ 3543.892748] Hardware name: ARM-Versatile Express
[ 3543.894048] [<8010f4bc>] (unwind_backtrace) from [<8010b3a8>] (show_stack+0x10/0x14)
[ 3543.894545] [<8010b3a8>] (show_stack) from [<808594c4>] (dump_stack+0x98/0xac)
[ 3543.895453] [<808594c4>] (dump_stack) from [<7f005014>] (hello_init+0x14/0x1000 [hello])
[ 3543.896038] [<7f005014>] (hello_init [hello]) from [<80101f80>] (do_one_initcall+0x58/0x244)
[ 3543.896457] [<80101f80>] (do_one_initcall) from [<801aab5c>] (do_init_module+0x60/0x228)
[ 3543.896821] [<801aab5c>] (do_init_module) from [<801ace94>] (load_module+0x2070/0x2484)
[ 3543.897200] [<801ace94>] (load_module) from [<801ad3ec>] (sys_init_module+0x144/0x184)
[ 3543.897548] [<801ad3ec>] (sys_init_module) from [<80100060>] (ret_fast_syscall+0x0/0x54)
[ 3543.898053] Exception stack(0x81a21fa8 to 0x81a21ff0)
[ 3543.898521] 1fa0:                   00000000 000151b4 002154d0 000151b4 001fdfd0 00000000
[ 3543.899033] 1fc0: 00000000 000151b4 00000000 00000080 7ec3ee48 7ec3ee4c 001fdfd0 001e967c
[ 3543.899481] 1fe0: 7ec3eb18 7ec3eb08 000367d0 00011350

版权声明:本文为qq_36393978原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。