前言Linux 內(nèi)核(以下簡稱內(nèi)核)是一個不與特定進(jìn)程相關(guān)的功能集合,內(nèi)核的代碼很難輕易的在調(diào)試器中執(zhí)行和跟蹤。開發(fā)者認(rèn)為,內(nèi)核如果發(fā)生了錯誤,就不應(yīng)該繼續(xù)運行。因此內(nèi)核發(fā)生錯誤時,它的行為通常被設(shè)定為系統(tǒng)崩潰,機(jī)器重啟?;趧討B(tài)存儲器的電氣特性,機(jī)器重啟后,上次錯誤發(fā)生時的現(xiàn)場會遭到破壞,這使得查找內(nèi)核的錯誤變得異常困難。 內(nèi)核社區(qū)和一些商業(yè)公司為此開發(fā)了很多種調(diào)試技術(shù)和工具,希望可以讓內(nèi)核的調(diào)試變得簡單。其中一種是單步跟蹤調(diào)試方法,即使用代碼調(diào)試器,一步步的跟蹤執(zhí)行的代碼,通過查看變量和寄存器的值來分析錯誤發(fā)生的原因。這一類的調(diào)試器有 gdb,kdb, kgdb。另一種方法是在系統(tǒng)崩潰時,將內(nèi)存保存起來,供事后進(jìn)行分析。多數(shù)情況下,單步調(diào)式跟蹤可以滿足需求,但是單步跟蹤調(diào)試也有缺點。如遇到如下幾種情況時:
單步調(diào)試跟蹤方法將無能為力。對于這幾種情況,在內(nèi)核發(fā)生錯誤并崩潰的時候,將內(nèi)存轉(zhuǎn)儲起來供事后分析就顯得尤為重要。本文接下來將介紹內(nèi)核的內(nèi)存轉(zhuǎn)儲機(jī)制以及如何對其進(jìn)行分析。 內(nèi)核的內(nèi)存轉(zhuǎn)儲機(jī)制由于 Linux 的開放性的緣故,在 Linux 下有好幾種內(nèi)存轉(zhuǎn)儲機(jī)制。下面將對它們分別做簡要的介紹。 LKCDLKCD(Linux Kernel Crash Dump) 是 Linux 下第一個內(nèi)核崩潰內(nèi)存轉(zhuǎn)儲項目,它最初由 SGI 的工程師開發(fā)和維護(hù)。它提供了一種可靠的方法來發(fā)現(xiàn)、保存和檢查系統(tǒng)的崩潰。LKCD 作為 Linux 內(nèi)核的一個補丁,它一直以來都沒有被接收進(jìn)入內(nèi)核的主線。目前該項目已經(jīng)完全停止開發(fā)。 DiskdumpDiskdump 是另外一個內(nèi)核崩潰內(nèi)存轉(zhuǎn)儲的內(nèi)核補丁,它由塔高 (Takao Indoh) 在 2004 年開發(fā)出來。與 LKCD 相比,Diskdump 更加簡單。當(dāng)系統(tǒng)崩潰時,Diskdump 對系統(tǒng)有完全的控制。為避免混亂,它首先關(guān)閉所有的中斷;在 SMP 系統(tǒng)上,它還會把其他的 CPU 停掉。然后它校驗它自己的代碼,如果代碼與初始化時不一樣。它會認(rèn)為它已經(jīng)被破壞,并拒絕繼續(xù)運行。然后 Diskdump 選擇一個位置來存放內(nèi)存轉(zhuǎn)儲。Diskdump 作為一個內(nèi)核的補丁,也沒有被接收進(jìn)入內(nèi)核的主線。在眾多的發(fā)行版中,它也只得到了 RedHat 的支持。 NetdumpRedHat 在它的 Linux 高級服務(wù)器 2.1 的版本中,提供了它自己的第一個內(nèi)核崩潰內(nèi)存轉(zhuǎn)儲機(jī)制:Netdump。 與 LKCD 和 Diskdump 將內(nèi)存轉(zhuǎn)儲保存在本地磁盤不同,當(dāng)系統(tǒng)崩潰時,Netdump 將內(nèi)存轉(zhuǎn)儲文件通過網(wǎng)絡(luò)保存到遠(yuǎn)程機(jī)器中。RedHat 認(rèn)為采用網(wǎng)絡(luò)方式比采用磁盤保的方式要簡單,因為當(dāng)系統(tǒng)崩潰時,可以在沒有中斷的情況下使用網(wǎng)卡的論詢模式來進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳送。同時,網(wǎng)絡(luò)方式對內(nèi)存轉(zhuǎn)儲文件提供了更好的管理支持。與 Diskdump 一樣,Netdump 沒有被接收進(jìn)入內(nèi)核的主線,目前也只有 RedHat 的發(fā)行版對 Netdump 提供支持。 KdumpKdump 是一種基于 kexec 的內(nèi)存轉(zhuǎn)儲工具,目前它已經(jīng)被內(nèi)核主線接收,成為了內(nèi)核的一部分,它也由此獲得了絕大多數(shù) Linux 發(fā)行版的支持。與傳統(tǒng)的內(nèi)存轉(zhuǎn)儲機(jī)制不同不同,基于 Kdump 的系統(tǒng)工作的時候需要兩個內(nèi)核,一個稱為系統(tǒng)內(nèi)核,即系統(tǒng)正常工作時運行的內(nèi)核;另外一個稱為捕獲內(nèi)核,即正常內(nèi)核崩潰時,用來進(jìn)行內(nèi)存轉(zhuǎn)儲的內(nèi)核。 在本文稍后的內(nèi)容中,將會介紹如何設(shè)置 kump。 MKdumpMKdump(mini kernel dump) 是 NTT 數(shù)據(jù)和 VA Linux 開發(fā)另一個內(nèi)核內(nèi)存轉(zhuǎn)儲工具,它與 Kdump 類似,都是基于 kexec,都需要使用兩個內(nèi)核來工作。其中一個是系統(tǒng)內(nèi)核;另外一個是 mini 內(nèi)核,用來進(jìn)行內(nèi)存轉(zhuǎn)儲。與 Kdump 相比,它有以下特點:
各種內(nèi)存轉(zhuǎn)儲分析工具與具有眾多的內(nèi)存轉(zhuǎn)儲機(jī)制一樣,Linux 下也有眾多的內(nèi)存轉(zhuǎn)儲分析工具,下面將會逐一做簡單介紹。 LcrashLcrash 是隨 LKCD 一起發(fā)布的一個內(nèi)內(nèi)存儲分析工具。隨著 LKCD 開發(fā)的停止,lcrash 的開發(fā)也同時停止了。目前它的代碼已經(jīng)被合并進(jìn)入 Crash 工具中。 AliciaAlicia (Advanced Linux Crash-dump Interactive Analyzer,高級 Linux 崩潰內(nèi)存轉(zhuǎn)儲交互分析器 ) 是一個建立在 lcrash 和 Crash 工具之上的一個內(nèi)存轉(zhuǎn)儲分析工具。它使用 Perl 語言封裝了 Lcrash 和 Crash 的底層命令,向用戶提供了一個更加友好的交互方式和界面。Alicia 目前的開發(fā)也已經(jīng)停滯。 CrashCrash 是由 Dave Anderson 開發(fā)和維護(hù)的一個內(nèi)存轉(zhuǎn)儲分析工具,目前它的最新版本是 5.0.0。 在沒有統(tǒng)一標(biāo)準(zhǔn)的內(nèi)存轉(zhuǎn)儲文件的格式的情況下,Crash 工具支持眾多的內(nèi)存轉(zhuǎn)儲文件格式,包括:
使用 Crash 分析內(nèi)存轉(zhuǎn)儲文件的例子通過前面的學(xué)習(xí),你現(xiàn)在可能已經(jīng)躍躍欲試了。本文接下來的部分,將以 kdump 為例子,向大家演示如何設(shè)置系統(tǒng)、如何產(chǎn)生內(nèi)存轉(zhuǎn)儲文件以及如何對內(nèi)存轉(zhuǎn)儲文件進(jìn)行分析。 kdump 的安裝設(shè)置如前面所述,支持 kdump 的系統(tǒng)使用兩個內(nèi)核進(jìn)行工作。目前一些發(fā)行版,如 RedHat 和 SUSE 的 Linux 都已經(jīng)編譯并設(shè)置好這兩個內(nèi)核。如果你使用其他發(fā)行版的 Linux 或者想自己編譯內(nèi)核支持 kdump,那么可以根據(jù)如下介紹進(jìn)行。 安裝 kexec
配置系統(tǒng)內(nèi)核和捕捉內(nèi)核都需要的內(nèi)核選項:
配置捕捉內(nèi)核的與架構(gòu)無關(guān)的選項:
配置捕捉內(nèi)核的與架構(gòu)相關(guān)的選項:Linux 內(nèi)核支持多種 CPU 架構(gòu),這里只介紹捕捉內(nèi)核在 i386 下的配置
加載新的系統(tǒng)內(nèi)核
加載捕捉內(nèi)核在系統(tǒng)內(nèi)核引導(dǎo)完成后,需要將捕捉內(nèi)核加載到內(nèi)存中。使用 kexec 工具將捕捉內(nèi)核加載到內(nèi)存: # kexec -p <dump-capture-kernel-bzImage> \ --initrd=<initrd-for-dump-capture-kernel> \ --append="root=<root-dev> <arch-specific-options>" 觸發(fā)內(nèi)核崩潰在捕捉內(nèi)核被加載進(jìn)入內(nèi)存后,如果系統(tǒng)崩潰開關(guān)被觸發(fā),則系統(tǒng)會自動切換進(jìn)入捕捉內(nèi)核。觸發(fā)系統(tǒng)崩潰的開關(guān)有 panic(),die(),die_nmi() 內(nèi)核函數(shù)和 sysrq 觸發(fā)事件,可以使用其中任意的一個來觸發(fā)內(nèi)核崩潰。不過,在讓內(nèi)核崩潰之前,我們還需要做一些安裝設(shè)置。 Crash 工具的安裝設(shè)置Crash 目前的最新的版本是 5.0.0, 你可以從它的官方網(wǎng)站下載最新的版本。下載完成后對其進(jìn)行解壓安裝。 # tar -zvxf crash-5.0.0.tar.gz # cd crash-5.0.0 # ./configure # make &&make install 生成內(nèi)存轉(zhuǎn)儲文件現(xiàn)在已經(jīng)設(shè)置好 Kdump 和 crash,現(xiàn)在可以使用前面介紹的系統(tǒng)崩潰開關(guān)中的任意一個來引發(fā)系統(tǒng)崩潰來生成一個內(nèi)存轉(zhuǎn)儲文件,并可以使用 crash 對其進(jìn)行分析。 首先,觸發(fā)系統(tǒng)崩潰,這里使用 sysrq 觸發(fā)事件。 # echo c > /proc/sysrq-trigger 緊接著,系統(tǒng)會自動啟動捕捉內(nèi)核。待完全啟動進(jìn)入捕捉內(nèi)核后,通過以下命令保存內(nèi)存轉(zhuǎn)儲文件。 # cp /proc/vmcore mydumpfile 將在當(dāng)前目錄生成一個 mydumpfile 文件。 分析內(nèi)存轉(zhuǎn)儲文件現(xiàn)在有了一個內(nèi)存轉(zhuǎn)儲文件,接下來使用 crash 對其進(jìn)行分析 # crash vmlinux mydumpfile 這里 vmlinux 是帶調(diào)試信息的內(nèi)核。如果一切正常,將會進(jìn)入到 crash 中,如圖 1 所示。 圖 1. crash 命令提示符![]() 在該提示符下,可以執(zhí)行 crash 的內(nèi)部命令。通過 crash 的內(nèi)部命令,可以查看寄存器的值、函數(shù)的調(diào)用堆棧等信息。在圖 2 中,顯示了執(zhí)行 圖 2. 函數(shù)調(diào)用堆棧信息![]() crash 使用 gdb 作為它的內(nèi)部引擎,crash 中的很多命令和語法都與 gdb 相同。如果你曾經(jīng)使用過 gdb,就會發(fā)現(xiàn) crash 并不是很陌生。如果想獲得 crash 更多的命令和相關(guān)命令的詳細(xì)說明,可以使用 crash 的內(nèi)部命令 后記本文介紹了 Linux 下的各種內(nèi)存轉(zhuǎn)儲機(jī)制,以及如何 crash 工具開對內(nèi)存轉(zhuǎn)儲文件進(jìn)行分析。內(nèi)核雖然復(fù)雜,但通過結(jié)合使用內(nèi)核的內(nèi)存轉(zhuǎn)儲文件和 crash 分析工具,可以輕松的找到內(nèi)核問題的所在。通過對這篇文章的學(xué)習(xí),相信你也可以像一個專業(yè)的內(nèi)核開發(fā)者那樣去追蹤和修復(fù)內(nèi)核的錯誤了。 參考資料學(xué)習(xí)
|
|