第十八章 調試git
調試工做艱難是內核級開發區別於用戶級開發的一個顯著特色。算法
1、準備開始架構
一、內和調試須要什麼函數
若是錯誤老是可以重現的話,消除錯誤的機會會很大。oop
2、內核中的bug性能
bug發做時可能的症狀:學習
3、經過打印來調試測試
printk()就是內核的格式化打印函數ui
一、健壯性spa
健壯性是printk()函數最容易讓人們接受的一個特質。任什麼時候候,任何地方都能調用它,內核中的printk()比比皆是。
負責執行硬件體系結構相關的初始化動做的函數是:setup_arch()
二、日誌等級
printk()和printf()在使用上最主要的區別就是前者能夠指定一個日誌級別。
內核根據這個級別來判斷是否在終端上打印消息。
內核把級別比某個特定值低的全部消息顯示在終端上。
可供使用的記錄等級:
默認等級:KERN_WARNING
三、記錄緩衝區
環形隊列的優缺點:
優勢:
缺點:
四、syslogd和klogd
4、oops
oops是內核告知用戶有不行法神最經常使用的方式。
oops中包含的重要信息對於全部體系結構都是徹底相同的:寄存器上下文和回溯線索。
是一個通過解碼的oops,由於內存地址都已經裝換成了對應的函數。
一、ksymoops
回溯線索中的地址須要轉化成有意義的符號名稱才方便使用,這須要調用ksymoops命令。而且還必須提供編譯內核時產生的System.map。若是使用的是模塊,還須要一些模塊信息。
而後該程序就會吐出解碼版的oops。若是ksymoops沒法找到默認位置上的信息,或者想提供不一樣信息,該程序能夠接受許多參數。
二、kallsyms
配置選項CONFIG_KALLSYMS_ALL 表示不只存放函數名稱,還存放全部的符號名稱。
5、內核調試配置選項
6、引起bug並打印信息
一些內核調用能夠用來方便標記bug方便標記bug提供斷言並輸出信息。
最經常使用的兩個是BUG()和些聲明BUG_ON()。當被調用的時候,它們會引起oops,致使棧的回溯和錯誤信息的打印。
7、神奇的系統請求鍵
啓用這個鍵的功能有2個方法:
開啓內核編譯選項 : CONFIG_MAGIC_SYSRQ
動態啓用: echo 1 > /proc/sys/kernel/sysrq
支持sysrq的命令:
8、內核調試器的傳奇
一、gdb
二、kgdb
kgdb是一個補丁,它可讓咱們在遠端主機上經過串口利用gdb的全部功能對內核進行調試。
這須要兩臺計算機:第一臺運行帶有kgdb補丁的內核,第二臺經過串行線使用gdb對第一臺進行調試。
經過kgdb的全部功能都能使用:讀取或修改變量值,設置斷點,設置關注變量,單步執行等。某些版本的gdb甚至容許執行函數。
9、探測系統
若是對內核調試有豐富的經驗的話,那麼你會掌握一些訣竅來幫助你更進一步地探測系統從而找到想要的答案。內核調試頗有挑戰性,即便是一點小的暗示或者技巧都能給你很大的幫助咱們最好把它們聯繫起來。
一、用UID做爲選擇條件
能夠利用把用戶id做爲選擇條件來實現這種功能,經過這種選擇條件,能夠安排到底執行哪一種算法。
if (current->uid != 7777) {
/* 老算法 */
} else {
/* 新算法 */
}
二、使用條件變量
三、使用統計量
當須要掌握某個特定事件的發生規律而且須要比較多個事件並從中得出規律能夠經過建立統計量並提供某種機制訪問其統計結果。
四、重複頻率限制
10、使用Git進行二分搜索
若是你使用Git來控制Linux源碼樹的副本,那麼Git將自動運行二分搜索進程。
Git會在修訂版本中進行二分搜索,這樣能夠找到具體哪次提交的代碼引起了bug。
11、小結
這一章講的是內核的調試。咱們學習了幾種技術:內核內置的調試架構、調試程序、記錄日誌、git二分法查找等。咱們知道了內和調試須要什麼一個bug(大部分bug一般都不是行爲可靠並且定義明確的)、一個藏匿bug的內核版本(知道bug最先出如今哪一個內核版本中)、相關內核代碼的知識和運氣(加深理解周圍的代碼)。以及內核中的bug可能發生的症狀等相關問題。