linux内核调试项

1、early printk   loglevel

       printk的log输出是由console实现(会在其他文章中说明)。由于在kernel刚启动的过程中,还没有为串口等设备等注册console(在device probe阶段实现),此时无法通过正常的console来输出log。
为此,linux提供了early console机制,用于实现为设备注册console之前的早期log的输出。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。

       CONFIG_DEBUG_LL
       ENTRY(printch)定义在arch/arm/debug.S中,需要用这个宏来打开。
       CONFIG_EARLY_PRINTK

       lichee\linux-3.10\arch\arm64\kernel\early_printk.c

                  linux内核调试项_第1张图片

 

2、initcall_debug

       initcall_debug参数定位初始化过程中的错误信息发生的位置。

                  linux内核调试项_第2张图片

                  linux内核调试项_第3张图片

 

 

3、内核打印

       Linux内核用函数printk打印调试信息,该函数的用法与C库打印函数printf格式类似,但在内核使用。用户可在内核代码中的某位置加入函数printk,直接把所关心的信息打打印到屏幕上或日志文件中。

       函数printk根据日志级别(loglevel)对调试信息进行分类。日志级别用宏定义,展开为一个字符串,在编译时由预处理器将它和消息文本拼接成一个字符串。

       (1)、不直接调用printk,而是调用pr_xxx,如下

                  

       (2)、不直接调用printk,而是调用dev_xxx

设备的名字将为打印前缀, dev_warn();     dev_info();    dev_emerg();

                  

       (3)、带函数与行数打印

                printk("%s%d\n", __func__, __LINE__);

       (4)、printk

                printk打印级别动态调整

                  

       printk有8个loglevel,定义在lichee\linux-3.10\include\linux\ kern_levels.h中,其中数值范围从0到7,数值越小,优先级越低。未指定优先级的默认级别定义在/kernel/printk.c中,当优先级的值小console_loglevel这个整数变量的值,信息才能显示出来

                    linux内核调试项_第4张图片

                   linux内核调试项_第5张图片 

      printk在中断,软中断,spinlock里面都可以调用。printk的开销很大,尤其是串口打印,会让系统慢很多,所以产品里面减少不必要的打印,或者bootargs里面"quiet"。

       (5)、内核带时间戳打印

                    linux内核调试项_第6张图片

 

       (6)、dumpstack()   warn_on(1)

       回溯函数调用过程。

 

4、内核模块源码级调试

       比较少用,参考kdb,gdb调试文档(待续,本人只用gdb调试过上层,没有调过内核,视频里面看也只是泛泛而讲)。

 

5、oops与panic

       Oops英文单词的中文含义是“哎呀”,表示“惊叹”;Panic英文单词的中文含义是“惊慌”。所以panic的程度显然是高于oops的,因为惊叹不一定会惊慌,而惊慌最容易失措,内核panic后,就死机了,俗称内核崩溃。但是内核报oops,这个时候不见得会panic,它可能只是报个oops,杀死进程而已。

oops不一定panic,中断上下文的oops会panic,如果panic_on_oops设置为1,一律panic。

       oops 显示发生错误时处理器的状态,包括 CPU 寄存器的内容、页描述符表的位置,以及其他一些信息。

                          linux内核调试项_第7张图片

 

 

                          

                         linux内核调试项_第8张图片

--->cd0+a0=d70

                        linux内核调试项_第9张图片

 

6、其他内核debug选项和功能

   (1)、 no_console_suspend

       在suspend的时候console 不进行suspend,否则console suspend之后其他driver在suspend 过程中印的log都显示不出来,因此加这个参数一般用于调试suspend 和 resume。在bootargs中添加"no_console_suspend"参数。

 

   (2)、SLUB_DEBUG   kmemleak  --->内存检测

  Linux常见的内存访问错误有:越界访问(out of bounds)、访问已经释放的内存(use after free)、重复释放、内存泄露(memory leak)、栈溢出(stack overflow)等。

       (a)、SLUB_DEBUG 内核中小块内存大量使用slab/slub分配器,slub_debug提供了:访问已经释放的内存、越界访问、重复释放内存等功能检测

支持slub_debug内核配置

重新配置kernel选项,打开如下选项即可。

CONFIG_SLUB=y

CONFIG_SLUB_DEBUG=y

CONFIG_SLUB_DEBUG_ON=y

                      linux内核调试项_第10张图片

                      linux内核调试项_第11张图片

                      linux内核调试项_第12张图片

 

   (1)、重复释放

                    linux内核调试项_第13张图片

                     linux内核调试项_第14张图片

 

                  

2c4+10c -> 3D0

                  linux内核调试项_第15张图片

      

       (2)、内存越界

                    linux内核调试项_第16张图片

 

                        linux内核调试项_第17张图片

       (b)、kmemleak是内核提供的一种检测内存泄露工具,启动一个内核线程扫描内存,并打印发现新的未引用对象数量。

        使用kmemlieak,需要打开如下内核选项。

CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=400
# CONFIG_DEBUG_KMEMLEAK_TEST is not set
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y---------
或者关闭此选项,则不需要在命令行添加kmemleak=on。

                       linux内核调试项_第18张图片

 

  (3)、DEBUG_ATOMIC_SLEEP  -->检测在spinlock,中断,软中断中的sleep

                         linux内核调试项_第19张图片

                     linux内核调试项_第20张图片

                         linux内核调试项_第21张图片

   (4)、RCU Stall

       内核配置项:

                      linux内核调试项_第22张图片

   (5)、Lockup detector

       kernel/watchdog.c

       NMI中断+定时器中断+高优先级RT线程

       用定时器中断,检测高优先级线程有无机会执行->softlockup

       用NMI,检测定时器中断有无机会执行->hard lockup

内核选项:

                     linux内核调试项_第23张图片

示例:

                   

                    linux内核调试项_第24张图片

你可能感兴趣的:(linux,android)