天天看點

Linux核心調試方法總結【轉】

核心開發比使用者空間開發更難的一個因素就是核心調試艱難。核心錯誤往往會導緻系統當機,很難保留出錯時的現場。調試核心的關鍵在于你的對核心的深刻了解。 

在調試一個bug之前,我們所要做的準備工作有: 

有一個被确認的bug。

包含這個bug的核心版本号,需要分析出這個bug在哪一個版本被引入,這個對于解決問題有極大的幫助。可以采用二分查找法來逐漸鎖定bug引入版本号。

對核心代碼了解越深刻越好,同時還需要一點點運氣。

該bug可以複現。如果能夠找到複現規律,那麼離找到問題的原因就不遠了。

最小化系統。把可能産生bug的因素逐一排除掉。

核心中的bug也是多種多樣的。它們的産生有無數的原因,同時表象也變化多端。從隐藏在源代碼中的錯誤到展現在目擊者面前的bug,其發作往往是一系列連鎖反應的事件才可能出發的。雖然核心調試有一定的困難,但是通過你的努力和了解,說不定你會喜歡上這樣的挑戰。 

學習編寫驅動程式要建構安裝自己的核心(标準主線核心)。最重要的原因之一是:核心開發者已經建立了多項用于調試的功能。但是由于這些功能會造成額外的輸出,并導緻能下降,是以發行版廠商通常會禁止發行版核心中的調試功能。 

為了實作核心調試,在核心配置上增加了幾項:

從核心2.5開發,為了檢查各類由原子操作引發的問題,核心提供了極佳的工具。 

核心提供了一個原子操作計數器,它可以配置成,一旦在原子操作過程中,進城進入睡眠或者做了一些可能引起睡眠的操作,就列印警告資訊并提供追蹤線索。 

是以,包括在使用鎖的時候調用schedule(),正使用鎖的時候以阻塞方式請求配置設定記憶體等,各種潛在的bug都能夠被探測到。 

下面這些選項可以最大限度地利用該特性: 

一些核心調用可以用來友善标記bug,提供斷言并輸出資訊。最常用的兩個是BUG()和BUG_ON()。

在标準的Linux系統上,使用者空間的守護程序klogd從紀錄緩沖區中擷取核心消息,再通過syslogd守護程序把這些消息儲存在系統日志檔案中。klogd程序既可以從/proc/kmsg檔案中,也可以通過syslog()系統調用讀取這些消息。預設情況下,它選擇讀取/proc方式實作。klogd守護程序在消息緩沖區有新的消息之前,一直處于阻塞狀态。一旦有新的核心消息,klogd被喚醒,讀出核心消息并進行處理。預設情況下,處理例程就是把核心消息傳給syslogd守護程序。syslogd守護程序一般把接收到的消息寫入/var/log/messages檔案中。不過,還是可以通過/etc/syslog.conf檔案來進行配置,可以選擇其他的輸出檔案。

Linux核心調試方法總結【轉】

dmesg 指令也可用于列印和控制核心環緩沖區。這個指令使用 klogctl 系統調用來讀取核心環緩沖區,并将它轉發到标準輸出(stdout)。這個指令也可以用來清除核心環緩沖區(使用 -c 選項),設定控制台日志級别(-n 選項),以及定義用于讀取核心日志消息的緩沖區大小(-s 選項)。注意,如果沒有指定緩沖區大小,那麼 dmesg 會使用 klogctl 的SYSLOG_ACTION_SIZE_BUFFER 操作确定緩沖區大小。 

a) 雖然printk很健壯,但是看了源碼你就知道,這個函數的效率很低:做字元拷貝時一次隻拷貝一個位元組,且去調用console輸出可能還産生中斷。是以如果你的驅動在功能調試完成以後做性能測試或者釋出的時候千萬記得盡量減少printk輸出,做到僅在出錯時輸出少量資訊。否則往console輸出無用資訊影響性能。 

b) printk的臨時緩存printk_buf隻有1K,所有一次printk函數隻能記錄<1K的資訊到log buffer,并且printk使用的“ringbuffer”. 

Linux核心調試方法總結【轉】

3.2  Kdump 實作流程

Linux核心調試方法總結【轉】

                     圖 1. RHEL6.2 執行流程

Linux核心調試方法總結【轉】

                                      圖 2. sles11 執行流程

3.3  配置 kdump

kgdb提供了一種使用 gdb調試 Linux 核心的機制。使用KGDB可以象調試普通的應用程式那樣,在核心中進行設定斷點、檢查變量值、單步跟蹤程式運作等操作。使用KGDB調試時需要兩台機器,一台作為開發機(Development Machine),另一台作為目标機(Target Machine),兩台機器之間通過序列槽或者以太網口相連。序列槽連接配接線是一根RS-232接口的電纜,在其内部兩端的第2腳(TXD)與第3腳(RXD)交叉相連,第7腳(接地腳)直接相連。調試過程中,被調試的核心運作在目标機上,gdb調試器運作在開發機上。 

目前,kgdb釋出支援i386、x86_64、32-bit PPC、SPARC等幾種體系結構的調試器。 

安裝kgdb調試環境需要為Linux核心應用kgdb更新檔,更新檔實作的gdb遠端調試所需要的功能包括指令處理、陷阱處理及序列槽通訊3個主要的部分。kgdb更新檔的主要作用是在Linux核心中添加了一個調試Stub。調試Stub是Linux核心中的一小段代碼,提供了運作gdb的開發機和所調試核心之間的一個媒介。gdb和調試stub之間通過gdb串行協定進行通訊。gdb串行協定是一種基于消息的ASCII碼協定,包含了各種調試指令。當設定斷點時,kgdb負責在設定斷點的指令前增加一條trap指令,當執行到斷點時控制權就轉移到調試stub中去。此時,調試stub的任務就是使用遠端串行通信協定将目前環境傳送給gdb,然後從gdb處接受指令。gdb指令告訴stub下一步該做什麼,當stub收到繼續執行的指令時,将恢複程式的運作環境,把對CPU的控制權重新交還給核心 

Linux核心調試方法總結【轉】

下面我們将以Linux 2.6.7核心為例詳細介紹kgdb調試環境的建立過程。 

2.1  軟硬體準備

以下軟硬體配置取自筆者進行試驗的系統配置情況: 

Linux核心調試方法總結【轉】

II、kgdb的啟動 

在将編譯出的核心拷貝的到target機器之後,需要配置系統引導程式,加入核心的啟動選項。以下是kgdb核心引導參數的說明: 

Linux核心調試方法總結【轉】

為了使讀者能夠更好地進行子產品的調試,kgdb項目還釋出了一些腳本程式能夠自動探測子產品的插入并自動更新gdb中子產品的符号資訊。這些腳本程式的工作原理與前面解釋的工作過程相似,更多的資訊請閱讀參考資料[4]。

2.5  硬體斷點 

kgdb提供對硬體調試寄存器的支援。在kgdb中可以設定三種硬體斷點:執行斷點(Execution Breakpoint)、寫斷點(Write Breakpoint)、通路斷點(Access Breakpoint)但不支援I/O通路的斷點。 目前,kgdb對硬體斷點的支援是通過宏來實作的,最多可以設定4個硬體斷點,這些宏的用法如下: 

Linux核心調試方法總結【轉】

在有些情況下,硬體斷點的使用對于核心的調試是非常友善的。 

kgdb調試環境需要使用兩台微機分别充當development機和target機,使用VMware後我們隻使用一台計算機就可以順利完成kgdb調試環境的搭建。以windows下的環境為例,建立兩台虛拟機,一台作為開發機,一台作為目标機。 

3.1  虛拟機之間的序列槽連接配接 

虛拟機中的序列槽連接配接可以采用兩種方法。一種是指定虛拟機的序列槽連接配接到實際的COM上,例如開發機連接配接到COM1,目标機連接配接到COM2,然後把兩個序列槽通過序列槽線相連接配接。另一種更為簡便的方法是:在較高一些版本的VMware中都支援把序列槽映射到命名管道,把兩個虛拟機的序列槽映射到同一個命名管道。例如,在兩個虛拟機中都標明同一個命名管道 \\.\pipe\com_1,指定target機的COM口為server端,并選擇"The other end is a virtual machine"屬性;指定development機的COM口端為client端,同樣指定COM口的"The other end is a virtual machine"屬性。對于IO mode屬性,在target上選中"Yield CPU on poll"複選擇框,development機不選。這樣,可以無需附加任何硬體,利用虛拟機就可以搭建kgdb調試環境。 即降低了使用kgdb進行調試的硬體要求,也簡化了建立調試環境的過程。 

Linux核心調試方法總結【轉】

3.2  VMware的使用技巧

VMware虛拟機是比較占用資源的,尤其是象上面那樣在Windows中使用兩台虛拟機。是以,最好為系統配備512M以上的記憶體,每台虛拟機至少配置設定128M的記憶體。這樣的硬體要求,對目前主流配置的PC而言并不是過高的要求。出于系統性能的考慮,在VMware中盡量使用字元界面進行調試工作。同時,Linux系統預設情況下開啟了sshd服務,建議使用SecureCRT登陸到Linux進行操作,這樣可以有較好的使用者使用界面。 

3.3  在Linux下的虛拟機中使用kgdb 

對于在Linux下面使用VMware虛拟機的情況,筆者沒有做過實際的探索。從原理上而言,隻需要在Linux下隻要建立一台虛拟機作為target機,開發機的工作可以在實際的Linux環境中進行,搭建調試環境的過程與上面所述的過程類似。由于隻需要建立一台虛拟機,是以使用Linux下的虛拟機搭建kgdb調試環境對系統性能的要求較低。(vmware已經推出了Linux下的版本)還可以在development機上配合使用一些其他的調試工具,例如功能更強大的cgdb、圖形界面的DDD調試器等,以友善核心的調試工作。 

Linux核心調試方法總結【轉】

使用kgdb作為核心調試環境最大的不足在于對kgdb硬體環境的要求較高,必須使用兩台計算機分别作為target和development機。盡管使用虛拟機的方法可以隻用一台PC即能搭建調試環境,但是對系統其他方面的性能也提出了一定的要求,同時也增加了搭建調試環境時複雜程度。另外,kgdb核心的編譯、配置也比較複雜,需要一定的技巧,筆者當時做的時候也是費了很多周折。當調試過程結束後時,還需要重新制作所要釋出的核心。使用kgdb并不能進行全程調試,也就是說kgdb并不能用于調試系統一開始的初始化引導過程。 

不過,kgdb是一個不錯的核心調試工具,使用它可以進行對核心的全面調試,甚至可以調試核心的中斷處理程式。如果在一些圖形化的開發工具的幫助下,對核心的調試将更友善。 

參考: 

SkyEye是一個開源軟體項目(OPenSource Software),SkyEye項目的目标是在通用的Linux和Windows平台上模拟常見的嵌入式計算機系統。SkyEye實作了一個指令級的硬體模拟平台,可以模拟多種嵌入式開發闆,支援多種CPU指令集。SkyEye 的核心是 GNU 的 gdb 項目,它把gdb和 ARM Simulator很好地結合在了一起。加入ARMulator 的功能之後,它就可以來仿真嵌入式開發闆,在它上面不僅可以調試硬體驅動,還可以調試作業系統。Skyeye項目目前已經在嵌入式系統開發領域得到了很大的推廣。 

由于探測器事件處理器是作為系統斷點中斷處理器的擴充來運作,是以它們很少或者根本不依賴于系統 工具 —— 這樣可以被植入到大部分不友好的環境中(從中斷時間和任務時間到禁用的上下文間切換和支援 SMP 的代碼路徑)—— 都不會對系統性能帶來負面影響。 

使用 Kprobes 的好處有很多。不需要重新編譯和重新開機核心就可以插入 printk。為了進行調試可以記錄 處理器寄存器的日志,甚至進行修改 —— 不會幹擾系統。類似地,同樣可以無幹擾地記錄 Linux 核心資料結構的日志,甚至 進行修改。您甚至可以使用 Kprobes 調試 SMP 系統上的競态條件 —— 避免了您自己重新編譯和重新開機的所有 麻煩。您将發現核心調試比以往更為快速和簡單。 

本文參考: 

1  Linux核心設計與實作   P243 第十八章 調試 

【新浪微網誌】 張昺華--sky

【twitter】 @sky2030_

【facebook】 張昺華 zhangbinghua

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.

繼續閱讀