ldd3學習之四 除錯技術

2021-07-29 17:31:24 字數 4025 閱讀 9405

核心中的除錯支援

核心開發者一般都已經建立了多項用於除錯的功能。但是由於這些功能會造成額外的輸出,並導致能下降,因此發行版廠商通常會禁止發行版核心中的除錯功能。

為了實現核心除錯,我在核心配置上增加了幾項:

kernel hacking  --->    

[*] magic sysrq key

[*] kernel debugging

[*]   debug slab memory allocations 

[*]   spinlock and rw-lock debugging: basic checks

[*]   spinlock debugging: sleep-inside-spinlock checking

[*]   compile the kernel with debug info 

[*] magic sysrq key

device drivers  ---> 

generic driver options  --->

[*] driver core verbose debug messages

general setup  --->

[*] configure standard kernel features (for small systems)  --->

[*]   load all symbols for debugging/ksymoops

書上介紹的還有其他配置。

方法一:printk ①

首先,printk有8個loglevel,定義在中: #

define    kern_emerg    "<0>"

/* system is unusable           */

#define    kern_alert    "<1>"

/* action must be taken immediately*/

#define    kern_crit    "<2>"

/* critical conditions    */

#define    kern_err    "<3>"

/* error conditions            */

#define    kern_warning    "<4>"

/* warning conditions   */

#define    kern_notice    "<5>"

/* normal but significant condition */

#define    kern_info    "<6>"

/* informational            */

#define    kern_debug    "<7>"

/* debug-level messages   */

未指定優先順序的預設級別定義在/kernel/printk.c中:

/* printk's without a loglevel use this.. */

#define default_message_loglevel 4 /* kern_warning */

當優先順序的值小於console_loglevel這個整數變數的值,資訊才能顯示出來。而console_loglevel的初始值default_console_loglevel也定義在/kernel/printk.c中: #

define default_console_loglevel 7 /* anything more serious than kern_debug */

還可以通過對/proc/sys/kernel/printk的訪問來改變console_loglevel的值

四個數字的含義:當前的loglevel、預設loglevel、最小允許的loglevel、引導時的預設loglevel。

linux訊息處理方法的乙個特點是:

可以在任何地方呼叫printk,甚至在終端處理函式裡也可以呼叫,而且對資料量的大小沒有限制,唯一缺點是可能丟失某些資料。

fdfdf

②為了方便的開啟和關閉除錯資訊,ldd3提供以下原始碼:

/* macros to help debugging */

#undef pdebug /* undef it, just in case */

#ifdef scull_debug

#ifdef __kernel__

/* this one if debugging is on, and kernel space */

#define pdebug(fmt, args...

) printk( kern_debug "scull: " fmt,

## args)

#else

/* this one for user space */

#define pdebug(fmt, args...

)fprintf

(stderr

, fmt,

## args)

#endif

#else

#define pdebug(fmt, args...

)/* not debugging: nothing */

#endif

#undef pdebugg

#define pdebugg(fmt, args...

)/* nothing: it's a placeholder */

makefile中要新增的語句:

# comment/uncomment the following line to disable/enable debugging

debug = y

# add your debugging flag (

ornot

) to cflags

ifeq (

$(debug)

,y)debflags =

-o -g -dscull_debug #

"-o" is needed to expand inlines

else

debflags =

-o2endif

cflags +

= $(debflags)

這些巨集是很有用的,僅有的缺點是每次開啟和關閉訊息顯示時,都要重新編譯模組。

③為了避免printk重複輸出過快而阻塞系統,核心使用以下函式跳過部分輸出

int printk_ratelimit(

void);

典型應用:

if(printk_ratelimit())

printk(kern_notice "the printer is still on fire\n");

可以通過修改/proc/sys/kernel/printk_ratelimit(重開資訊前應等待的秒數)和/proc/sys/kernel/printk_ratelimit_burst(在速度限制前可接受的資訊數)來定製printk_ratelimit的行為。

linux還提供了列印裝置編號的巨集(在

中定義):

int print_dev_t(

char

*buffer, dev_t dev)

;char

*format_dev_t(

char

*buffer, dev_t dev);

兩個函式的唯一區別是:print_dev_t返回列印字元數,format_dev_t返回緩衝區指標。注意緩衝區char

*buffer的大小應至少有20b。

方法二:oops

1.oops是核心級的segmentation fault。

應用程式-->訪問非法記憶體或非法指令-->segment訊號-->行為是coredump

kernel-->列印oops資訊

2.分析步驟

①錯誤提示原因

②呼叫棧(對照反彙編**)  back tree:

③暫存器。 pc is at fun+0x1c/0x30

pc-->fun函式0x1c偏移處,0x30是fun長度

0 給主人留下些什麼吧!~~

LDD3學習筆記(7) 除錯技術

1 核心中的除錯 開發中需要啟用的配置選項 config debug kernel config debug slab config debug pagealloc config debug spinlock config debug spinlock sleep config init debug...

LDD3原始碼學習日記《四》

日記三不小心被刪了。哎,只能在 站裡面自己看了。這部落格80 的功能還是寫給自己看的,其他部分的功能應該是用來練習寫作能力的,留下這一路走來的證據,兩年後回過頭來看看自己當初是怎麼犯低階錯誤的。哈哈。第五章是併發與競態,書上的內容講的主要是訊號量和自旋鎖機制,還有completion,不過書上介紹這...

LDD3原始碼學習筆記之scull pipe轉

pipe.c 驅動功能分析 本驅動使用環形緩衝作為scull裝置的的具體實現,類似於pipe.其中實現了阻塞的i o讀寫和非同步通知.主函式流程分析 1.定義scull pipe裝置機構體 2.初始化模組module init scull p init 3.退出並登出模組module exit sc...