|
2008 年 12 月 24 日
kdb 是專門用于執(zhí)行系統(tǒng)轉儲映像分析的實用工具。本文將將介紹系統(tǒng)轉儲分析的基本步驟。
簡介
對于基本的轉儲分析,本文主要解釋轉儲映像。我們將介紹如何從 snap 包中提取相應的文件,接著介紹一種檢查轉儲的系統(tǒng)方法,然后探查引起系統(tǒng)崩潰的根本原因。轉儲文件和 UNIX ? 文件位于 snap 包的 dump 子目錄中。
雖然我們考察的重點是轉儲映像,但是適當?shù)厥褂?snap 選項還可以獲得有用的信息,這點很重要。更多信息請閱讀本文的 General 和 Kernel 小節(jié)。
General
general 目錄包括有關系統(tǒng)運行時環(huán)境的信息,例如:
- ODM 數(shù)據(jù)拷貝。
- 所有環(huán)境變量(例如 PATH 和 TZ)。
- 數(shù)據(jù)收集的日期和時間。
- 系統(tǒng)的實際內存量(bootinfo -r)。
- 所有已定義頁面空間的列表。
- 所有已安裝文件集及其級別的列表。
- 所有已安裝 APAR 的列表。
- 設備屬性(lsattr -El)。
- 系統(tǒng) VPD 信息(lscfg -pv)。
- 上一次轉儲的狀態(tài)(sysdumpdev -L)。
Kernel
kernel 子目錄包含了有用的內核信息(進程和內存數(shù)據(jù))。
- 數(shù)據(jù)收集的日期和時間。
- vmstat 輸出。
- VMM 可調信息(vmo -L)。
- 調度可調信息(schedo -L)。
- 與 I/O 有關的可調信息(ioo -L)。
- 環(huán)境變量。
- SRC 信息(lssrc -a)。
- 進程信息(ps -ef 和 ps -leaf)。
- 設備驅動器和方法的校驗和。
提取 snap 包
使用 pax 命令從 snap 包中提取文件。
- 要查看 snap 文件的內容,輸入以下命令:
# zcat snap.pax.Z | pax -v
|
- 要提取該包的所有內容,輸入以下命令:
# zcat snap.pax.Z | pax -r
|
- 要僅提取 dump、general 和 kernel 子目錄,輸入:
#uncompress snap.pax.Z
#zcat snap.pax.Z | pax -r ./dump ./general ./kernel
|
kdb 是什么?
kdb 實用工具檢查當前運行系統(tǒng)的操作系統(tǒng)映像,并且與 IBM? AIX? 內核緊密耦合。這是因為它要求使用內核的結構信息來準確地格式化系統(tǒng)轉儲映像中包含的信息。kdb 為查看和格式化數(shù)據(jù)結構提供了大量子命令。
KDB - 內核調試器
kdb 是一個交互式內核調試器。kdb 允許用戶控制內核代碼的執(zhí)行(包括內核擴展和設備驅動器),并觀察和修改變量和寄存器。它必須由一個特殊的啟動映像調用。
kdb 是一個分析系統(tǒng)轉儲的工具/命令。它用于對系統(tǒng)轉儲進行事后分析,或用于監(jiān)視運行中的內核。
調用 kdb
kdb 在檢查系統(tǒng)轉儲時通過兩個參數(shù)調用。第一個參數(shù)指定系統(tǒng)映像,而第二個參數(shù)指定轉儲期間系統(tǒng)運行的內核的 UNIX 文件。UNIX 文件必須匹配轉儲映像(比如,發(fā)生崩潰時正在運行的映像)。如果不匹配的話,kdb 將顯示一個錯誤消息并退出。
如果沒有使用參數(shù)調用,kdb 將檢查當前正在運行的系統(tǒng)的映像。
獲取轉儲狀態(tài)
對轉儲映像調用 kdb 之后,首先使用 stat 子命令檢索基本轉儲狀態(tài):
圖 1. Stat 輸出
kdb 的 stat 子命令提供了正在查看的轉儲的信息。除了包含日期、時間、版本和發(fā)布信息外,還包含轉儲原因代碼。
轉儲原因代碼
如果由于系統(tǒng)檢測到問題而發(fā)起轉儲,那么 stat 子命令的輸出將包含標題為 CRASH INFORMATION 的部分。
- 該部分中,輸出的第一行列出了檢測到問題的 CPU,這些問題造成轉儲例程被調用(在前面的示例中 CPU 為 0)。
- 轉儲原因代碼指文本 “error code for LEDs” 旁邊顯示的數(shù)字的前三位。在前面的示例中,CRASH INFORMATION 部分的前三位包含以下文本:
error code for LEDs: 30000000
|
這意味著轉儲原因代碼為 300,即 DSI(DATA STORAGE INTERRUPT)。
轉儲原因代碼表示造成崩潰的基本原因。大多數(shù)崩潰通常顯示的原因代碼為 300、400 和 700。
| 原因代碼 |
說明 |
| 2nn |
機器檢查 |
| 3nn |
數(shù)據(jù)存儲中斷 |
| 400 |
指令存儲中斷 |
| 5nn |
外部中斷 |
| 700 |
程序中斷 |
| 800 |
浮點數(shù)據(jù)不可用 |
- 2nn-機器檢查。
機器檢查原因代碼通常表示硬件問題(比如,內存損壞)。
- 3nn-數(shù)據(jù)存儲中斷(DSI)。
如果對當前不在物理內存中加載的虛擬地址進行引用(這是一個頁面錯誤),則會出現(xiàn) DSI 錯誤。頁面錯誤是經(jīng)常發(fā)生的錯誤。通常由 VMM 處理,并且不會導致系統(tǒng)崩潰。然而,如果頁面錯誤不能夠在內核模式下解決,或者在禁用中斷情況下出現(xiàn)頁面錯誤,那么 DIS 將造成系統(tǒng)崩潰。這個問題通常由軟件引起,但是偶爾也和硬件有關。
- 400-指令存儲中斷(ISI)。
指令存儲中斷通常是指在取出指令時發(fā)生頁面錯誤。這種錯誤通常通過 VMM 解決,并且一般不會造成系統(tǒng)崩潰。如果不能夠通過 VMM 解決,或者在禁用中斷的情況下發(fā)生頁面錯誤,那么將造成系統(tǒng)崩潰。
- 5nn-外部中斷。
引起崩潰的原因是外部設備出現(xiàn)中斷,比如 I/O 總線控制器。
- 700-程序中斷。
這種類型的中斷是由內核例程調用了 trap 指令引起的。這通常是調用 panic 內核服務或斷言失敗造成的。內核例程在遇到無法解決的問題時就會調用 panic 服務。這種問題通常和軟件有關,但也可能和硬件也有關。
- 800-浮點不可用。
如果在 MSR(機器狀態(tài)寄存器)中可用的浮點位被禁用,將嘗試執(zhí)行一個浮點指令。
初始 CPU 上下文
kdb 永遠在運行崩潰線程的 CPU 上下文中啟動。當調用 kdb 時,顯示以下提示:(n)>>,其中的 n 表示當前的 CPU 上下文。
然而,要切換到另一個 CPU 上下文,可以使用 cpu 子命令:
MST (MACHINE STATE SAVE AREA)
Machine State save area(MST)包含已保存的 CPU 進程上下文的映像。進程上下文包含通用寄存器、浮點寄存器、特殊用途的寄存器和其他有關重啟線程所需的信息。CPU 上的每個處理器都擁有自己的 CSA(當前保存區(qū))指針,指向當線程或中斷處理程序由于上下文切換而被中斷或交換時使用的 MST。雖然線程是活動的,但是運行線程的處理器的 CSA 將指向當前活動線程的 MST。
圖 3. mst 子命令在 64 位內核中的輸出
圖 4. mst 子命令在 32 位內核中的輸出
mst 子命令輸出中的數(shù)據(jù)字段
prev 和 intpri 字段中的值幫助判斷處理器是在運行線程還是在運行中斷處理程序。
如果 CPU 正在運行一個線程,該線程可以位于處理上下文或中斷上下文中。中斷處理程序始終在中斷上下文中運行。
圖 5. 處理-中斷上下文
處理環(huán)境與中斷環(huán)境之間的主要差別是:當處于中斷環(huán)境中時,不允許出現(xiàn)任何頁面錯誤。
Machine State Register (MSR)
每個 CPU 都有自己的 MSR,它表示處理器的狀態(tài)。
dr msr /* dr cmd 用于轉儲任何寄存器 */ 的內容
(0)> dr msr
msr : 0000F0B2 bit set : EE PR FP ME IR DR RI
|
圖 6. MST 寄存器
分析 MSR 數(shù)據(jù)
在討論系統(tǒng)轉儲時,我們只關注在 CPU 中運行的引起系統(tǒng)崩潰的東西。
如果在 MSR 中設置了 PR 位(問題狀態(tài)),那么 CPU 在用戶模式下運行,并且不可能引起系統(tǒng)崩潰。因為用戶模式指令沒有引起系統(tǒng)崩潰的足夠權限。
如果轉儲原因代碼為 300 或 400,我們必須對異常結構進行分析。
圖 7. 異常結構
我們必須對 mst 輸出中的值進行分析。特別要檢查 IAR 引用的指令,證實它引起的崩潰類型是 stat 子命令報告的類型。
VMM 錯誤日志
圖 9. Vmlog 輸出
在 VMM 提供崩潰原因時,vmlog 子命令提供額外的信息。代碼 300 轉儲中顯示的 Error ID 是 DSI_PROC,而在代碼 400 轉儲中為 ISI_PROC。Exception DSISR/ISISR,srval,virt addr 包含異常結構中顯示的信息。Exception 值是一個內部 VMM 錯誤代碼。
棧跟蹤
f [threadtableslot | threadtableaddress]
|
它顯示線程的內核模式棧跟蹤。
如果沒有提供任何參數(shù),則顯示當前 CPU 上下文的棧跟蹤。
圖 10. 跟蹤輸出
圖 11. DSI 示例
上圖顯示了 stat 命令的輸出。輸出顯示錯誤代碼為 300,表明這是一個 DSI 崩潰。
圖 12. DSI 跟蹤
上圖顯示的棧跟蹤描述了當 CPU 0 上的某個線程運行 function __memmove 時出現(xiàn)的問題。
圖 13. mst 命令輸出
mst 子命令的輸出表示線程(表示為 prev =0)在啟用了所有中斷的情況下運行(表示為 intpri =0B)。換句話說,線程正在進程環(huán)境中運行。
異常結構的 dsisr 字段由兩項組成,DSISR_PROT 和 DSISR_ST。DSISR_PROT 字段表示出現(xiàn)保護違反(protection violation)。DSISR_ST 表示問題與存儲操作有關。引起頁面錯誤的數(shù)據(jù)地址為 0x00(dar 0000000000000000)。
異常結構 dsisr 字段的 DSISR_ST 表示存儲操作出了問題。我們希望 IAR 引用某種形式的存儲指令。
0)> dc @iar
___memmove64+000058 std r7,8(r3)
|
r7 的當前內容將被存儲到內存地址中(向 r3 的當前值加 0x08 得出該地址)。從 mst 子命令的輸出可以看到,r3 的當前值是 FFFFFFFFFFFFFFF8,因此向 FFFFFFFFFFFFFFF8 加 0x08 將得到:
(0)> hcal FFFFFFFFFFFFFFF8+0x08
Value hexa: 00000000 Value decimal: 0
|
這意味著 r7 的當前內容將被保存到地址 0X00。它匹配異常結構中 dar 字段顯示的值。
內核地址空間中的第一頁虛擬內存可通過內核代碼訪問,但是被標記為只讀。任何對該內存范圍執(zhí)行寫操作的嘗試將導致保護違反。
進程和線程
proc 子命令
在使用 asterix (*) 調用 proc 子命令時,它將以一行摘要顯示進程表中的所有活動進程。
當使用進程表地址或 slot 編號調用 proc 子命令時,它將詳細顯示指定地址或 slot 的格式化進程信息(如果在未使用參數(shù)的情況下調用 proc 子命令,它將詳細顯示當前進程的格式化進程信息)。
圖 14. proc 命令輸出
圖 15. pid 輸出
thread 子命令
當使用 asterix (*) 調用 thread 子命令時,它將以一行摘要顯示線程表中的所有活動線程。
當使用線程表地址或 slot 編號調用 thread 子命令時,它將詳細顯示指定線程的格式化線程信息(如果在未使用參數(shù)的情況下調用 thread 子命令,它將詳細顯示當前線程的格式化線程信息)。
圖 16. thread 命令輸出
圖 17. tid 輸出
當前線程和進程
status 子命令列出了所有 CPU 的當前線程和進程的信息。
圖 18. status 命令輸出
其他 kdb 子命令
- 無參數(shù) lke 子命令列出當前加載的擴展。
- ts 子命令將地址轉換為符號表示。
- CALCULATORS-Use hcal 用于十六進制計算,dcal 用于十進制計算。
- 記錄 kdb session-(0)>set 日志文件的文件名。
日志級別可設為 0、1 或 2。這決定將哪種信息記錄到日志文件中。值 0 表示禁止記錄到日志文件中。值 1 表示只記錄在提示時輸入的 kdb 命令。值 2 記錄 kdb 會話的輸入和輸出。
結束語
查找系統(tǒng)崩潰的根本原因是一個單調乏味的過程,因此了解 kdb 非常有用,它供一種分析系統(tǒng)崩潰的系統(tǒng)方法。通過 kdb,您將能夠迅速跟蹤導致系統(tǒng)崩潰問題。此外,您還學習到一種很有價值技能,借助它不僅能夠節(jié)省大量調試時間,還可以了解可以避免系統(tǒng)崩潰的編程實踐。最后這點也很重要,這是一種可以快速解決崩潰問題的系統(tǒng)性方法,它將幫助您贏得客戶信任。
|