Linux中國

Linux 內核測試與調試(3)

檢查內核日誌

使用 dmesg 查看隱藏的問題,對於定位新代碼帶來的 bug 是一個好方法。一般來說,dmesg 不會輸出新的 crit, alert, emerg 級別的錯誤信息,也不應該出現新的 err 級別的信息。你要注意的是那些 warn 級別的日誌信息。請注意 warn 這個級別的信息並不是壞消息,新代碼帶來新的警告信息,不會給內核帶去嚴重的影響。

  • dmesg -t -l emerg
  • dmesg -t -l crit
  • dmesg -t -l alert
  • dmesg -t -l err
  • dmesg -t -l warn
  • dmesg -t -k
  • dmesg -t

下面的腳本運行了上面的命令,並且將輸出保存起來,以便與老的內核的 dmesg 輸出作比較(LCTT:老內核的 dmesg 輸出在本系列的第二篇文章中有介紹)。然後運行 diff 命令,查看新老內核 dmesg 日誌之間的不同。這個腳本需要輸入老內核版本號,如果不輸入參數,它只會生成新內核的 dmesg 日誌文件後直接退出,不再作比較(LCTT:話是這麼說沒錯,但點開腳本一看,沒輸參數的話,這貨會直接退出,連新內核的 dmesg 日誌也不會保存的)。如果 dmesg 日誌有新的警告信息,表示新發布的內核有漏網之「蟲」,這些 bug 逃過了自測和系統測試。你要看看,那些警告信息後面有沒有棧跟蹤信息?也許這裡有很多問題需要你進一步調查分析。

壓力測試

執行壓力測試的一個好辦法是同時跑三四個內核編譯任務。下載各種版本的內核,同時編譯它們,並記錄時間。比較新內核跑壓力測試和老內核跑壓力測試所花的時間,然後可以定位新內核的性能。如果新內核跑壓力測試的時間比老內核的更長,說明新內核的部分模塊性能退步了。性能問題很難調試出來。第一步是找出哪裡導致的性能退步。同時跑多個內核編譯任務對檢測內核整體性能來說是個好方法,但是這種方法涵蓋了多個內核模塊,比如內存管理、文件系統、DMA、驅動等(LCTT:也就是說,這種壓力測試沒辦法定位到是哪個模塊造成了性能的下降)。

time make all

內核測試工具

我們可以在 Linux 內核本身找到多種測試方法。下面介紹一個很好用的功能測試工具集: ktest 套件

ktest 是一個自動測試套件,它可以提供編譯安裝啟動內核一條龍測試服務,也可以跑交叉編譯測試,前提是你的系統有安裝交叉編譯所需要的軟體。ktest 依賴於 flex 和 bison。詳細信息請參考放在 tools/testing/ktest 目錄下的文檔,你可以自學成材。另外還有一些參考資料教你怎麼使用 ktest:

tools/testing/selftests 套件

我們來玩玩自測吧。內核源碼的多個子系統都有自己的自測工具,到目前為止,斷點、cpu熱插拔、efivarfs、IPC、KCMP、內存熱插拔、mqueue、網路、powerpc、ptrace、rcutorture、定時器和虛擬機子系統都有自測工具。另外,用戶態內存的自測工具可以利用 testusercopy 模塊來測試用戶態內存到內核態的拷貝過程。下面的命令演示了如何使用這些測試工具:

編譯測試:

make -C tools/testing/selftests 

測試全部:(有些測試需要 root 許可權,你需要以 root 用戶登入系統然後運行命令)

make -C tools/testing/selftests run_tests 

只測試單個子系統:

make -C tools/testing/selftests TARGETS=vm run_tests 

tools/testing/fault-injection 套件

在 tools/testing 目錄下的另一個測試套件是 fault-injection。failcmd.sh 腳本用於檢測 slab 和內存頁分配器的錯誤。這些工具可以測試內核能否很好地從錯誤狀態中恢復回來。這些測試需要用到 root 許可權。下面簡單介紹了一些當前能提供的錯誤檢測方法。隨著錯誤檢測方法的增加,這份名單也會不斷增長。最新的名單請參考 Documentation/fault-injection/fault-injection.txt 文檔。

failslab (默認選項)

產生 slab 分配錯誤。作用於 kmalloc(), kmemcachealloc() 等函數(LCTT:產生的結果是調用這些函數就會返回失敗,可以模擬程序分不到內存時是否還能穩定運行下去)。

fail_page_alloc

產生內存頁分配的錯誤。作用於 allocpages(), getfree_pages() 等函數(LCTT:同上,調用這些函數,返回錯誤)。

fail_make_request

對滿足條件(可以設置 /sys/block//make-it-fail 或 /sys/block///make-it-fail 文件)的磁碟產生 IO 錯誤,作用於 generic_make_request() 函數(LCTT:所有針對這塊磁碟的讀或寫請求都會出錯)。

fail_mmc_request

對滿足條件(可以設置 /sys/kernel/debug/mmc0/fail_mmc_request 這個 debugfs 屬性)的磁碟產生 MMC 數據錯誤。

你可以自己配置 fault-injection 套件的功能。fault-inject-debugfs 內核模塊在系統運行時會在 debugfs 文件系統下面提供一些屬性文件。你可以指定出錯的概率,指定兩個錯誤之間的時間間隔,當然本套件還能提供更多其他功能,具體請查看 Documentation/fault-injection/fault-injection.txt。 Boot 選項可以讓你的系統在 debugfs 文件系統起來之前就可以產生錯誤,下面列出幾個 boot 選項:

  • failslab=
  • fail_page_alloc=
  • fail_make_request=
  • mmc_core.fail_request=[interval],[probability],[space],[times]

fault-injection 套件提供介面,以便增加新的功能。下面簡單介紹下增加新功能的步驟,詳細信息請參考上面提到過的文檔:

使用 DECLAREFAULT**INJECTION(name) 定義默認屬性;

詳細信息可查看 fault-inject.h 中定義的 struct fault_attr 結構體。

配置 fault 屬性,新建一個 boot 選項;

這步可以使用 setup_fault_attr(attr, str) 函數完成,為了能在系統啟動的早期產生錯誤,添加一個 boot 選項這一步是必須要有的。

添加 debugfs 屬性;

使用 fault_create_debugfs_attr(name, parent, attr) 函數,為新功能添加新的 debugfs 屬性。

為模塊設置參數;

為模塊添加一些參數,對於配置錯誤屬性來說是一個好主意,特別是當新功能的應用範圍受限於單個內核模塊的時候(LCTT:不同內核,你的新功能可能需要不同的測試參數,通過設置參數,你的功能可以不必為了迎合不同內核而每次都重新編譯一遍)。

添加一個鉤子函數到錯誤測試的代碼中。

should_fail(attr, size) —— 當這個鉤子函數返回 true 時,用戶的代碼就應該產生一個錯誤。

應用程序使用這個 fault-injection 套件可以指定某個具體的內核模塊產生 slab 和內存頁分配的錯誤,這樣就可以縮小性能測試的範圍。

via: http://www.linuxjournal.com/content/linux-kernel-testing-and-debugging?page=0,2

譯者:bazz2 校對:wxy

本文由 LCTT 原創翻譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國