盡管Linux作為是一個操作系統,但歸根結底,它仍然是一個程序。由于Linux是一個程序,因此可以通過debug來調試。但是,由于環境的不同,使用的方法和工具也不同。那么如何調試Linux內核?如何區別Linux的內核?Gdb是Linux下的常見調試工具,而Windows上的更多調試工具都是基于接口的。直接對應的中間變量的值和所請求存儲器的地址將直觀顯示。在Linux上,主要通過命令查看它。實際上,它是命令的行的使用,這也是一些常見的命令。
如何調試Linux內核?
一、調試前的準備
內核級bug具有行為不可靠,定義不清晰或者說很難再現的諸多特定,為內核級的bug跟蹤和調試帶來了很大的困難。
對于一些定義不清楚地bug,問題的關鍵就是找到bug的源頭,很多時候,當你精確地重現一個bug的時候,你就離成功不遠了。
二、內核中的bug
從隱藏在源代碼中的錯誤到展現在目擊者面前的bug,其發作往往是一系列連鎖反應的事件才可能出發的。
雖然內核調試有一定的困難,但是通過你的努力和理解,說不定你會喜歡上這樣的挑戰。
三、printk()
內核提供的格式化打印函數。
1、printk函數的健壯性
健壯性是printk最容易被接受的一個特質,幾乎在任何地方,任何時候內核都可以調用它(中斷上下文、進程上下文、持有鎖時、多處理器處理時等)。
在系統啟動過程中,終端初始化之前,在某些地方是不能調用的。
2、記錄等級
printk函數可以指定一個記錄級別,內核根據這個級別來判斷是否在終端上打印消息。
記錄級別定義在中。
調用方式:printk(KER_DEBUG“Thisisadebugnotice!/n”);內核用這個指定的紀錄等級和當前終端的紀錄等級console_loglevel比較,來決定是不是向終端打印。
3、記錄緩沖區
內核消息都被保存在一個LOG_BUF_LEN大小的環形隊列中。
關于LOG_BUF_LEN定義:
#define__LOG_BUF_LEN(1<
變量CONFIG_LOG_BUF_SHIFT在內核編譯時由配置文件定義,對于i386平臺,其值定義如下(在Linux26/arch/i386/defconfig中):
CONFIG_LOG_BUF_SHIFT=18
緩沖區操作:
①消息被讀出到用戶空間時,此消息就會從環形隊列中刪除。
②當消息緩沖區滿時,如果再有printk()調用時,新消息將覆蓋隊列中的老消息。
③在讀寫環形隊列時,同步問題很容易得到解決。
這個紀錄緩沖區之所以稱為環形,是因為它的讀寫都是按照環形隊列的方式進行操作的。
4、syslogd和klogd
在標準的Linux系統上,用戶空間的守護進程klogd從紀錄緩沖區中獲取內核消息,再通過syslogd守護進程把這些消息保存在系統日志文件中。klogd進程既可以從/proc/kmsg文件中,也可以通過syslog()系統調用讀取這些消息。默認情況下,它選擇讀取/proc方式實現。klogd守護進程在消息緩沖區有新的消息之前,一直處于阻塞狀態。一旦有新的內核消息,klogd被喚醒,讀出內核消息并進行處理。默認情況下,處理例程就是把內核消息傳給syslogd守護進程。
syslogd守護進程一般把接收到的消息寫入/var/log/messages文件中。不過,還是可以通過/etc/syslog.conf文件來進行配置,可以選擇其他的輸出文件。
四、OOPS
作為內核的開發者,必定將會經常處理OOPS。
ksymoops
在Linux中,調試系統崩潰的傳統方法是分析在發生崩潰時發送到系統控制臺的Oops消息。一旦您掌握了細節,就可以將消息發送到ksymoops實用程序,它將試圖將代碼轉換為指令并將堆棧值映射到內核符號。
ksymoops需要幾項內容:Oops消息輸出、來自正在運行的內核的System.map文件,還有/proc/ksyms、vmLinux和/proc/modules。
關于如何使用ksymoops,內核源代碼/usr/src/Linux/Documentation/oops-tracing.txt中或ksymoops手冊頁上有完整的說明可以參考。Ksymoops反匯編代碼部分,指出發生錯誤的指令,并顯示一個跟蹤部分表明代碼如何被調用。
#cat/proc/kallsyms
c0100240T_stext
c0100240trun_init_process
c0100240Tstext
c0100269tinit
五、內核調試配置選項
在編譯內核的時候,為了方便調試和測試代碼,內核提供了許多配置選項。
調試原子操作
從內核2.5開發,為了檢查各類由原子操作引發的問題,內核提供了極佳的工具。
內核提供了一個原子操作計數器,它可以配置成,一旦在原子操作過程中,進城進入睡眠或者做了一些可能引起睡眠的操作,就打印警告信息并提供追蹤線索。
所以,包括在使用鎖的時候調用schedule(),正使用鎖的時候以阻塞方式請求分配內存等,各種潛在的bug都能夠被探測到。
下面這些選項可以最大限度地利用該特性:
CONFIG_PREEMPT=y
CONFIG_DEBUG_KERNEL=y
CONFIG_KLLSYMS=y
CONFIG_SPINLOCK_SLEEP=y
六、引發bug并打印信息
1、一些內核調用可以用來方便標記bug,提供斷言并輸出信息。最常用的兩個是BUG()和BUG_ON()。
當調用這兩個宏的時候,它們會引發OOPS,導致棧的回溯和錯誤消息的打印。
2、dump_stack()
有些時候,只需要在終端上打印一下棧的回溯信息來幫助你調試。這時可以使用dump_stack()。這個函數只在終端上打印寄存器上下文和函數的跟蹤線索。
if(!debug_check){
printk(KERN_DEBUG“providesomeinformation…/n”);
dump_stack();
}
如何區別Linux的內核?
Linux是一種開源電腦操作系統內核。它是一個用C語言寫成,符合POSIX標準的類Unix操作系統。Linux最早是由芬蘭黑客LinusTorvalds為嘗試在英特爾x86架構上提供自由免費的類Unix操作系統而開發的。該計劃開始于1991年,在計劃的早期有一些Minix黑客提供了協助,而今天全球無數程序員正在為該計劃無償提供幫助。
內核不止一種,所以我們應該怎么區別呢?
Linux的內核版本有兩種:1穩固版2開發版。
Linux內核版本號是由3個數字構成:a.b.c
a:目前發布的內核主版本。
b:偶數表示穩固版本;奇數表示開發中版本。
c:錯誤修補的次數。
其中第一個數字是主版本號,第二個數字是次版本號,第三個數字是修訂版本號。
上述就是關于如何調試Linux內核,以及如何區別Linux內核的全部內容,想了解更多關于Linux的信息,請繼續關注中培偉業。