天天看點

使用 Crash 工具分析 Linux dump 檔案

前言

  Linux 核心(以下簡稱核心)是一個不與特定程序相關的功能集合,核心的代碼很難輕易的在調試器中執行和跟蹤。開發者認為,核心如果發生了錯誤,就不應該繼續運作。是以核心發生錯誤時,它的行為通常被設定為系統崩潰,機器重新開機。基于動态存儲器的電氣特性,機器重新開機後,上次錯誤發生時的現場會遭到破壞,這使得查找核心的錯誤變得異常困難。

  核心社群和一些商業公司為此開發了很多種調試技術和工具,希望可以讓核心的調試變得簡單。其中一種是單步跟蹤調試方法,即使用代碼調試器,一步步的跟蹤執行的代碼,通過檢視變量和寄存器的值來分析錯誤發生的原因。這一類的調試器有 gdb,kdb, kgdb。另一種方法是在系統崩潰時,将記憶體儲存起來,供事後進行分析。多數情況下,單步調式跟蹤可以滿足需求,但是單步跟蹤調試也有缺點。如遇到如下幾種情況時:

  • 錯誤發生在客戶的機器上。
  • 錯誤發生在很關鍵的生産機器上。
  • 錯誤很難重制。

  單步調試跟蹤方法将無能為力。對于這幾種情況,在核心發生錯誤并崩潰的時候,将記憶體轉儲起來供事後分析就顯得尤為重要。本文接下來将介紹核心的記憶體轉儲機制以及如何對其進行分析。

核心的記憶體轉儲機制

  由于 Linux 的開放性的緣故,在 Linux 下有好幾種記憶體轉儲機制。下面将對它們分别做簡要的介紹。

LKCD

  LKCD(Linux Kernel Crash Dump) 是 Linux 下第一個核心崩潰記憶體轉儲項目,它最初由 SGI 的工程師開發和維護。它提供了一種可靠的方法來發現、儲存和檢查系統的崩潰。LKCD 作為 Linux 核心的一個更新檔,它一直以來都沒有被接收進入核心的主線。目前該項目已經完全停止開發。

Diskdump

  Diskdump 是另外一個核心崩潰記憶體轉儲的核心更新檔,它由塔高 (Takao Indoh) 在 2004 年開發出來。與 LKCD 相比,Diskdump 更加簡單。當系統崩潰時,Diskdump 對系統有完全的控制。為避免混亂,它首先關閉所有的中斷;在 SMP 系統上,它還會把其他的 CPU 停掉。然後它校驗它自己的代碼,如果代碼與初始化時不一樣。它會認為它已經被破壞,并拒絕繼續運作。然後 Diskdump 選擇一個位置來存放記憶體轉儲。Diskdump 作為一個核心的更新檔,也沒有被接收進入核心的主線。在衆多的發行版中,它也隻得到了 RedHat 的支援。

Netdump

  RedHat 在它的 Linux 進階伺服器 2.1 的版本中,提供了它自己的第一個核心崩潰記憶體轉儲機制:Netdump。 與 LKCD 和 Diskdump 将記憶體轉儲儲存在本地磁盤不同,當系統崩潰時,Netdump 将記憶體轉儲檔案通過網絡儲存到遠端機器中。RedHat 認為采用網絡方式比采用磁盤保的方式要簡單,因為當系統崩潰時,可以在沒有中斷的情況下使用網卡的論詢模式來進行網絡資料傳送。同時,網絡方式對記憶體轉儲檔案提供了更好的管理支援。與 Diskdump 一樣,Netdump 沒有被接收進入核心的主線,目前也隻有 RedHat 的發行版對 Netdump 提供支援。

Kdump

  Kdump 是一種基于 kexec 的記憶體轉儲工具,目前它已經被核心主線接收,成為了核心的一部分,它也由此獲得了絕大多數 Linux 發行版的支援。與傳統的記憶體轉儲機制不同不同,基于 Kdump 的系統工作的時候需要兩個核心,一個稱為系統核心,即系統正常工作時運作的核心;另外一個稱為捕獲核心,即正常核心崩潰時,用來進行記憶體轉儲的核心。 在本文稍後的内容中,将會介紹如何設定 kump。

MKdump

  MKdump(mini kernel dump) 是 NTT 資料和 VA Linux 開發另一個核心記憶體轉儲工具,它與 Kdump 類似,都是基于 kexec,都需要使用兩個核心來工作。其中一個是系統核心;另外一個是 mini 核心,用來進行記憶體轉儲。與 Kdump 相比,它有以下特點:

  • 将記憶體儲存到磁盤。
  • 可以将記憶體轉儲鏡像轉換到 lcrash 支援格式。
  • 通過 kexec 啟動時,mini 核心覆寫第一個核心。

各種記憶體轉儲分析工具

  與具有衆多的記憶體轉儲機制一樣,Linux 下也有衆多的記憶體轉儲分析工具,下面将會逐一做簡單介紹。

Lcrash

  Lcrash 是随 LKCD 一起釋出的一個内記憶體儲分析工具。随着 LKCD 開發的停止,lcrash 的開發也同時停止了。目前它的代碼已經被合并進入 Crash 工具中。

Alicia

  Alicia (Advanced Linux Crash-dump Interactive Analyzer,進階 Linux 崩潰記憶體轉儲互動分析器 ) 是一個建立在 lcrash 和 Crash 工具之上的一個記憶體轉儲分析工具。它使用 Perl 語言封裝了 Lcrash 和 Crash 的底層指令,向使用者提供了一個更加友好的互動方式和界面。Alicia 目前的開發也已經停滞。

Crash

  Crash 是由 Dave Anderson 開發和維護的一個記憶體轉儲分析工具,目前它的最新版本是 5.0.0。 在沒有統一标準的記憶體轉儲檔案的格式的情況下,Crash 工具支援衆多的記憶體轉儲檔案格式,包括:

  • Live linux 系統
  • kdump 産生的正常的和壓縮的記憶體轉儲檔案
  • 由 makedumpfile 指令生成的壓縮的記憶體轉儲檔案
  • 由 Netdump 生成的記憶體轉儲檔案
  • 由 Diskdump 生成的記憶體轉儲檔案
  • 由 Kdump 生成的 Xen 的記憶體轉儲檔案
  • IBM 的 390/390x 的記憶體轉儲檔案
  • LKCD 生成的記憶體轉儲檔案
  • Mcore 生成的記憶體轉儲檔案

使用 Crash 分析記憶體轉儲檔案的例子

  通過前面的學習,你現在可能已經躍躍欲試了。本文接下來的部分,将以 kdump 為例子,向大家示範如何設定系統、如何産生記憶體轉儲檔案以及如何對記憶體轉儲檔案進行分析。

kdump 的安裝設定

  如前面所述,支援 kdump 的系統使用兩個核心進行工作。目前一些發行版,如 RedHat 和 SUSE 的 Linux 都已經編譯并設定好這兩個核心。如果你使用其他發行版的 Linux 或者想自己編譯核心支援 kdump,那麼可以根據如下介紹進行。

安裝 kexec

  1. 使用 root 使用者登入系統。
  2. 使用 wget 從 Internet 上下載下傳 kexec。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    wget http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/\

    2.

    kexec-tools.

    tar

    .gz

  3. 解壓并安裝 kexec 到系統中。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    # tar xvpzf kexec-tools.tar.gz 

    2.

    # cd kexec-tools-VERSION 

    3.

    # ./configure 

    4.

    # make && make install

配置系統核心和捕捉核心都需要的核心選項:

  • 在 "Processor type and features."選項中啟用"kexec system call"。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_KEXEC=y

  • 在"Filesystem" -> "Pseudo filesystems." 中啟用"sysfs file system support"。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_SYSFS=y

  • 在"Kernel hacking."中啟用"Compile the kernel with debug info"。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_DEBUG_INFO=Y

配置捕捉核心的與架構無關的選項:

  • 在"Processor type and features"中啟用"kernel crash dumps"。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_CRASH_DUMP=y

  • 在"Filesystems" -> "Pseudo filesystems"中啟用"/proc/vmcore support"。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_PROC_VMCORE=y

配置捕捉核心的與架構相關的選項:

  Linux 核心支援多種 CPU 架構,這裡隻介紹捕捉核心在 i386 下的配置

  • 在"Processor type and features"中啟用高端記憶體支援。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_HIGHMEM64G=y

  • 在"Processor type and features"中關閉多處理器支援。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_SMP=n

  • 在"Processor type and features"中啟用"Build a relocatable kernel"。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_RELOCATABLE=y

  • 在"Processor type and features"->"Physical address where the kernel is loaded"中,為核心設定一個加載起始位址。在大多數的機器上,16M 是一個合适的值。

    檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

    1.

    CONFIG_PHYSICAL_START=0x1000000

加載新的系統核心

  1. 編譯系統核心和捕捉核心。
  2. 将重新編譯好的核心添加到啟動引導中,注意不要将捕捉核心添加到啟動引導菜單中。
  3. 給系統核心添加啟動參數"[email protected]",這裡,Y 是為 dump 捕捉核心保留的記憶體,X 是保留部分記憶體的開始位置。在 i386 的機器上,設定"[email protected]"。
  4. 重新開機機器,在啟動菜單中選擇新添加的啟動項,啟動新的系統核心。

加載捕捉核心

  在系統核心引導完成後,需要将捕捉核心加載到記憶體中。使用 kexec 工具将捕捉核心加載到記憶體:

檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

1.

# kexec -p <dump-capture-kernel-bzImage> \ 

2.

--initrd=<initrd-

for

-dump-capture-kernel> \ 

3.

--append=

"root=<root-dev> <arch-specific-options>"

觸發核心崩潰

  在捕捉核心被加載進入記憶體後,如果系統崩潰開關被觸發,則系統會自動切換進入捕捉核心。觸發系統崩潰的開關有 panic(),die(),die_nmi() 核心函數和 sysrq 觸發事件,可以使用其中任意的一個來觸發核心崩潰。不過,在讓核心崩潰之前,我們還需要做一些安裝設定。

Crash 工具的安裝設定

  Crash 目前的最新的版本是 5.0.0, 你可以從它的官方網站下載下傳最新的版本。下載下傳完成後對其進行解壓安裝。

檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

1.

# tar -zvxf crash-5.0.0.tar.gz 

2.

# cd crash-5.0.0 

3.

# ./configure 

4.

# make &&make install

生成記憶體轉儲檔案

  現在已經設定好 Kdump 和 crash,現在可以使用前面介紹的系統崩潰開關中的任意一個來引發系統崩潰來生成一個記憶體轉儲檔案,并可以使用 crash 對其進行分析。

  首先,觸發系統崩潰,這裡使用 sysrq 觸發事件。

檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

1.

# echo c > /proc/sysrq-trigger

緊接着,系統會自動啟動捕捉核心。待完全啟動進入捕捉核心後,通過以下指令儲存記憶體轉儲檔案。

檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

1.

# cp /proc/vmcore mydumpfile

  将在目前目錄生成一個 mydumpfile 檔案。

分析記憶體轉儲檔案

  現在有了一個記憶體轉儲檔案,接下來使用 crash 對其進行分析

檢視源代碼 列印 ? ·········10········20········30········40········50········60········70········80········90

1.

# crash vmlinux mydumpfile

  這裡 vmlinux 是帶調試資訊的核心。如果一切正常,将會進入到 crash 中,如圖 1 所示。

圖 1. crash 指令提示符
使用 Crash 工具分析 Linux dump 檔案

  在該提示符下,可以執行 crash 的内部指令。通過 crash 的内部指令,可以檢視寄存器的值、函數的調用堆棧等資訊。在圖 2 中,顯示了執行 bt指令後得到的函數調用的堆棧資訊。

圖 2. 函數調用堆棧資訊
使用 Crash 工具分析 Linux dump 檔案

  crash 使用 gdb 作為它的内部引擎,crash 中的很多指令和文法都與 gdb 相同。如果你曾經使用過 gdb,就會發現 crash 并不是很陌生。如果想獲得 crash 更多的指令和相關指令的詳細說明,可以使用 crash 的内部指令 help來擷取。

後記

  本文介紹了 Linux 下的各種記憶體轉儲機制,以及如何 crash 工具開對記憶體轉儲檔案進行分析。核心雖然複雜,但通過結合使用核心的記憶體轉儲檔案和 crash 分析工具,可以輕松的找到核心問題的所在。通過對這篇文章的學習,相信你也可以像一個專業的核心開發者那樣去追蹤和修複核心的錯誤了。

繼續閱讀