核心中的除錯支援
核心開發者一般都已經建立了多項用於除錯的功能。但是由於這些功能會造成額外的輸出,並導致能下降,因此發行版廠商通常會禁止發行版核心中的除錯功能。
為了實現核心除錯,我在核心配置上增加了幾項:
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...