中文字幕亚洲第一精品|精品国产免费一区二区|久久婷婷五月六月综合版|中文字幕熟妇久久久人妻|久久综合精品国产一区无码|国产成人精品永久免费视频|午夜亚洲国产精品理论片a级|久久精品一区二区三区无码护土

 訪問(wèn)手機(jī)版  

Linux內(nèi)核|Linux內(nèi)核學(xué)習(xí)培訓(xùn)|怎么學(xué)Linux|Linux認(rèn)證,首選超級(jí)網(wǎng)工!

招聘|合作 登陸|注冊(cè)

網(wǎng)絡(luò)工程師培訓(xùn)

當(dāng)前位置:網(wǎng)絡(luò)工程師 > 技術(shù)課程 > linux > 熱點(diǎn)關(guān)注 > linux內(nèi)核

你會(huì)調(diào)試你的Linux內(nèi)核嗎?

時(shí)間:2018-07-05

Linux內(nèi)核在使用一段時(shí)間之后,可能會(huì)出現(xiàn)bag,所以需要進(jìn)行調(diào)試。雖然內(nèi)核調(diào)試是一件艱苦的工作,但是為了運(yùn)行更加流暢,還是需要進(jìn)行內(nèi)核調(diào)試。那怎么進(jìn)行內(nèi)核調(diào)試呢?
一、調(diào)試前的準(zhǔn)備   
內(nèi)核級(jí)bug具有行為不可靠,定義不清晰或者說(shuō)很難再現(xiàn)的諸多特定,為內(nèi)核級(jí)的bug跟蹤和調(diào)試帶來(lái)了很大的困難。   
對(duì)于一些定義不清楚地bug,問(wèn)題的關(guān)鍵就是找到bug的源頭,很多時(shí)候,當(dāng)你精確地重現(xiàn)一個(gè)bug的時(shí)候,你就離成功不遠(yuǎn)了。
二、內(nèi)核中的bug   
從隱藏在源代碼中的錯(cuò)誤到展現(xiàn)在目擊者面前的bug,其發(fā)作往往是一系列連鎖反應(yīng)的事件才可能出發(fā)的。   
雖然內(nèi)核調(diào)試有一定的困難,但是通過(guò)你的努力和理解,說(shuō)不定你會(huì)喜歡上這樣的挑戰(zhàn)。
三、printk( )  
內(nèi)核提供的格式化打印函數(shù)。  
1、printk函數(shù)的健壯性     
健壯性是printk最容易被接受的一個(gè)特質(zhì),幾乎在任何地方,任何時(shí)候內(nèi)核都可以調(diào)用它(中斷上下文、進(jìn)程上下文、持有鎖時(shí)、多處理器處理時(shí)等)。    
在系統(tǒng)啟動(dòng)過(guò)程中,終端初始化之前,在某些地方是不能調(diào)用的。    
2、記錄等級(jí)    
printk函數(shù)可以指定一個(gè)記錄級(jí)別,內(nèi)核根據(jù)這個(gè)級(jí)別來(lái)判斷是否在終端上打印消息。    
記錄級(jí)別定義在<linux/kernel.h>中。
調(diào)用方式:printk(KER_DEBUG “This is a debug notice!/n”);  內(nèi)核用這個(gè)指定的紀(jì)錄等級(jí)和當(dāng)前終端的紀(jì)錄等級(jí)console_loglevel比較,來(lái)決定是不是向終端打印。
3、記錄緩沖區(qū)   
內(nèi)核消息都被保存在一個(gè)LOG_BUF_LEN大小的環(huán)形隊(duì)列中。   
關(guān)于LOG_BUF_LEN定義:   
#define __LOG_BUF_LEN     (1 << CONFIG_LOG_BUF_SHIFT)   
變量CONFIG_LOG_BUF_SHIFT在內(nèi)核編譯時(shí)由配置文件定義,對(duì)于i386平臺(tái),其值定義如下(在linux26/arch/i386/defconfig中):   
CONFIG_LOG_BUF_SHIFT=18     
緩沖區(qū)操作:   
①消息被讀出到用戶空間時(shí),此消息就會(huì)從環(huán)形隊(duì)列中刪除。   
②當(dāng)消息緩沖區(qū)滿時(shí),如果再有printk()調(diào)用時(shí),新消息將覆蓋隊(duì)列中的老消息。   
③在讀寫環(huán)形隊(duì)列時(shí),同步問(wèn)題很容易得到解決。   
這個(gè)紀(jì)錄緩沖區(qū)之所以稱為環(huán)形,是因?yàn)樗淖x寫都是按照環(huán)形隊(duì)列的方式進(jìn)行操作的。
4、syslogd和klogd   
在標(biāo)準(zhǔn)的Linux系統(tǒng)上,用戶空間的守護(hù)進(jìn)程klogd從紀(jì)錄緩沖區(qū)中獲取內(nèi)核消息,再通過(guò)syslogd守護(hù)進(jìn)程把這些消息保存在系統(tǒng)日志文件中。klogd進(jìn)程既可以從/proc/kmsg文件中,也可以通過(guò)syslog()系統(tǒng)調(diào)用讀取這些消息。默認(rèn)情況下,它選擇讀取/proc方式實(shí)現(xiàn)。klogd守護(hù)進(jìn)程在消息緩沖區(qū)有新的消息之前,一直處于阻塞狀態(tài)。一旦有新的內(nèi)核消息,klogd被喚醒,讀出內(nèi)核消息并進(jìn)行處理。默認(rèn)情況下,處理例程就是把內(nèi)核消息傳給syslogd守護(hù)進(jìn)程。   
syslogd守護(hù)進(jìn)程一般把接收到的消息寫入/var/log/messages文件中。不過(guò),還是可以通過(guò)/etc/syslog.conf文件來(lái)進(jìn)行配置,可以選擇其他的輸出文件。
四、OOPS
作為內(nèi)核的開發(fā)者,必定將會(huì)經(jīng)常處理OOPS。
1、ksymoops    
在 Linux 中,調(diào)試系統(tǒng)崩潰的傳統(tǒng)方法是分析在發(fā)生崩潰時(shí)發(fā)送到系統(tǒng)控制臺(tái)的 Oops 消息。一旦您掌握了細(xì)節(jié),就可以將消息發(fā)送到 ksymoops 實(shí)用程序,它將試圖將代碼轉(zhuǎn)換為指令并將堆棧值映射到內(nèi)核符號(hào)。
ksymoops需要幾項(xiàng)內(nèi)容:Oops 消息輸出、來(lái)自正在運(yùn)行的內(nèi)核的 System.map 文件,還有 /proc/ksyms、vmlinux 和 /proc/modules。
關(guān)于如何使用 ksymoops,內(nèi)核源代碼 /usr/src/linux/Documentation/oops-tracing.txt 中或 ksymoops 手冊(cè)頁(yè)上有完整的說(shuō)明可以參考。Ksymoops 反匯編代碼部分,指出發(fā)生錯(cuò)誤的指令,并顯示一個(gè)跟蹤部分表明代碼如何被調(diào)用。
#cat /proc/kallsyms     
c0100240   T       _stext     
c0100240   t       run_init_process     
c0100240   T      stext     
c0100269   t       init
五、內(nèi)核調(diào)試配置選項(xiàng)  
在編譯內(nèi)核的時(shí)候,為了方便調(diào)試和測(cè)試代碼,內(nèi)核提供了許多配置選項(xiàng)。
調(diào)試原子操作  
從內(nèi)核2.5開發(fā),為了檢查各類由原子操作引發(fā)的問(wèn)題,內(nèi)核提供了極佳的工具。  
內(nèi)核提供了一個(gè)原子操作計(jì)數(shù)器,它可以配置成,一旦在原子操作過(guò)程中,進(jìn)城進(jìn)入睡眠或者做了一些可能引起睡眠的操作,就打印警告信息并提供追蹤線索。  
所以,包括在使用鎖的時(shí)候調(diào)用schedule(),正使用鎖的時(shí)候以阻塞方式請(qǐng)求分配內(nèi)存等,各種潛在的bug都能夠被探測(cè)到。  
下面這些選項(xiàng)可以最大限度地利用該特性:  
CONFIG_PREEMPT = y  
CONFIG_DEBUG_KERNEL = y  
CONFIG_KLLSYMS = y  
CONFIG_SPINLOCK_SLEEP = y
六、引發(fā)bug并打印信息
1、一些內(nèi)核調(diào)用可以用來(lái)方便標(biāo)記bug,提供斷言并輸出信息。最常用的兩個(gè)是BUG()和BUG_ON()。
當(dāng)調(diào)用這兩個(gè)宏的時(shí)候,它們會(huì)引發(fā)OOPS,導(dǎo)致棧的回溯和錯(cuò)誤消息的打印。
2、dump_stack()    
有些時(shí)候,只需要在終端上打印一下棧的回溯信息來(lái)幫助你調(diào)試。這時(shí)可以使用dump_stack()。這個(gè)函數(shù)只在終端上打印寄存器上下文和函數(shù)的跟蹤線索。    
if (!debug_check) {        
printk(KERN_DEBUG “provide some information…/n”);        
dump_stack();    
}