Linux內核棧信息獲取與理解

Linux內核棧信息獲取與理解

From: http://www.ilinuxkernel.com/files/2/Linux_kernel_stack.html

內核棧獲取

C語言的函數調用,是通過棧來實現的。如下圖所示:

    1.  函數調用棧

內核異常或死機時,經常在內核日誌中看到打印的棧信息和寄存器值。從函數棧信息,我們可以知道函數間的調用關係,從棧和寄存器數據,還可以得到各個變量、參數的值。對Linux內核理解和故障定位非常有幫助。


若希望打印出棧信息的函數中加上dump_stack()即可,dump_stack()已導出到內核符號表中,可直接調用。

00276: / *

00277: * The architecture- independent dump_stack generator

00278: */

00279: void dump_stack(void)

00280: {

00281: unsigned long stack;

00282:

00283: show_trace(current, NULL, &stack);

00284: }

00285:

00286: EXPORT_SYMBOL(dump_stack);

00287:


若是內核代碼,則需要重新編譯內核。若是內核模塊,編譯後,重新加載該模塊。注意要控制好打印棧信息的次數和頻度。內核中有些代碼是大量被執行的,這時要控制打印次數,否則系統長時間無法響應。

下面棧信息是在文件fs/jbd/transaction.c,函數journal_dirty_data()中加入dump_stack()函數後的獲取到的棧信息。

內核棧信息的理解

對於Linux內核棧信息來說,也主要是函數的調用關係。


如下面棧信息:


對於語句:

[<c03743c8>] smp_scan_config+0xa9/0xcb


因爲是最後一個函數,c03743c8dump_stack()函數的地址。

linux:~ # cat /proc/kallsyms |grep smp_scan_config

c037431f t smp_scan_config


通過查找內核符號表,我們看到smp_scan_config()函數在內核中的地址是c037431f


+0xa9/0xcb”0xa9含義是當前函數在上一層函數內的偏移量。對於本句來說,就是dump_stack()函數在smp_scan_config()內核的偏移量爲0xa9,行首打印的地址是c037431f + a9 = c03743c8 。“0xcb”表示smp_scan_config()函數代碼大小爲0xcb


同理,我們知道在find_smp_config()函數中調用了smp_scan_config()函數,調用該函數的位置是代碼c037441c處,偏移量爲0x32find_smp_config()函數大小爲0x5c


打印內核棧信息的原理是:將棧中的值都作地址對待,然後根據地址,首先查看該地址是否屬於內核代碼(text)段或初始代碼(inittext)段中的函數。若是,則打印函數信息。

if (is_kernel_text(addr) || is_kernel_inittext(addr))

00165: const char *kallsyms_lookup(unsigned long addr,

00166: unsigned long *symbolsize,

00167: unsigned long *offset,

00168: char **modname, char *namebuf)

… …

00179: if ((all_var && is_kernel(addr)) ||

00180: (! all_var && (is_kernel_text(addr) ||

00181: is_kernel_inittext(addr)|| is_kernel_extratext(addr)))) {

… …


若不是內核代碼(text)段或初始代碼(inittext)段中的函數,那麼進而查找是爲模塊(驅動)中的函數。若是,則打印函數信息。


00224: / * see if it's in a module */

00225: msym = module_address_lookup(addr, symbolsize, offset,

modname);

00226: if (msym)

00227: return strncpy(namebuf, msym, KSYM_NAME_LEN);


若既不是內核代碼(text)段或初始代碼(inittext)段中的函數,也不是模塊(驅動)中的函數;那麼什麼信息都不打印,繼續取棧中的值,直到棧底。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章