核心調試工具 — kdump & crash

來源:互聯網
上載者:User
kdump簡介

 

kdump是系統崩潰的時候,用來轉儲運行記憶體的一個工具。

系統一旦崩潰,核心就沒法正常工作了,這個時候將由kdump提供一個用於捕獲當前運行資訊的核心,

該核心會將此時記憶體中的所有運行狀態和資料資訊收集到一個dump core檔案中以便之後分析崩潰原因。

一旦記憶體資訊收集完成,可以讓系統將自動重啟。

 

kdump是RHEL5之後才支援的,2006被主線接收為核心的一部分。它的原理簡單來說是在記憶體中保留一塊

地區,這塊地區用來存放capture kernel,當production kernel發生crash的時候,通過kexec把保留地區的

capure kernel給運行起來,再由捕獲核心負責把產品核心的完整資訊 - 包括CPU寄存器、堆棧資料等轉儲

到指定位置的檔案中。

  kdump原理

 

kexec是kdump機制的關鍵,包含兩部分:

核心空間的系統調用kexec_load。負責在生產核心啟動時將捕獲核心載入到指定地址。

使用者空間的工具kexec-tools。將捕獲核心的地址傳遞給生產核心,從而在系統崩潰的時候找到捕獲核心的地址並運行。

 

kdump是一種基於kexec的核心崩潰轉儲機制。當系統崩潰時,kdump使用kexec啟動到第二個核心。第二個核心通常

叫做捕獲核心,以很小記憶體啟動以捕獲轉儲鏡像。第一個核心保留了記憶體的一部分給第二個核心啟動使用。

由於kdump利用kexec啟動捕獲核心,繞過了BIOS,所以第一個核心的記憶體得以保留。這是記憶體崩潰轉儲的本質。

捕獲核心啟動後,會像一般核心一樣,去運行為它建立的ramdisk上的init程式。而各種轉儲機制都可以事先在init中實現。

為了在生產核心崩潰時能順利啟動捕獲核心,捕獲核心以及它的ramdisk是事先放到生產核心的記憶體中的。

生產核心的記憶體是通過/proc/vmcore這個檔案交給捕獲核心的。為了產生它,使用者工具在生產核心中分析出記憶體的使用和

分布等情況,然後把這些資訊綜合起來產生一個ELF標頭檔儲存起來。捕獲核心被引導時會被同時傳遞這個ELF檔案頭的

地址,通過分析它,捕獲核心就可以產生出/proc/vmcore。有了/proc/vmcore這個檔案,捕獲核心的ramdisk中的指令碼就

可以通過通常的檔案讀寫和網路來實現各種策略了。

  kdump配置

 

RHEL5開始,kexec-tools是預設安裝的。

如果需要調試kdump產生的vmcore檔案,需要手動安裝kernel-debuginfo包。

 

(1) 預留記憶體

可以修改核心引導參數,為啟動捕獲核心預留指定記憶體。

在/etc/grub.conf (一般為/boot/grub/grub.conf的軟連結)中:

crashkernel=Y@X,Y是為kdump捕獲核心保留的記憶體,X是保留部分記憶體的起始位置。

預設為crashkernel=auto,可自行設定如crashkernel=256M。

 

(2) 設定檔

設定檔為/etc/kdump.conf,以下是幾個常用配置:

 

# path /var/crash

預設的vmcore存放目錄為/var/crash/%HOST-%DATE/,包括兩個檔案:vmcore和vmcore-dmesg.txt

 

# ssh <user@service>

will copy /proc/vmcore to <user@server>:<path>/%HOST-%DATE/ via SSH

make sure user has necessary write permissions on server.

自動拷貝到遠程機器上。

 

# default <reboot | halt | poweroff | shell | mount_root_run_init>

Actions to perform in case dumping to intended target fails.

轉儲失敗時執行。

 

(3) 啟動服務

# chkconfig kdump on // 開機啟動

# service kdump status // start、stop、restart等

 

(4) 功能驗證

Magic System request key is a magical key combo you can hit which the kernel will respond to regardless

of whatever else it is doing, unless it is completely locked up.

使用sysrq需要編譯選項CONFIG_MAGIC_SYSRQ的支援。詳細資料可看documentation/sysrq.txt。

 

故意讓系統崩潰,來測試kdump是否正常工作。

# echo c > /proc/sysrq-trigger

Will perform a system crash by a NULL pointer dereference.

A crash dump will be taken if configured.

 

Magic SysRq還有一些很有趣的值,有的具有很大的破環性,輸出在/var/log/messages:

f:call oom_kill to kill a memory hog process. 執行oom killer。

l:shows a stack backtrace for all active CPUs. 列印出所有CPU的stack backtrace。

m:dump current memory info. 列印出記憶體使用量資訊。

p:dump the current registers and flags. 列印出所在CPU的寄存器資訊。

 

(5) 捕獲核心

捕獲核心是一個未壓縮的ELF映像檔案,查看捕獲核心是否載入到記憶體中:

# cat /sys/kernel/kexec_crash_loaded

縮小捕獲核心佔用的記憶體:

# echo N > /sys/kernel/kexec_crash_size

  crash簡介

 

當系統崩潰時,通過kdump可以獲得當時的記憶體轉儲檔案vmcore,但是該如何分析vmcore呢。

crash是一個用於分析核心轉儲檔案的工具,一般和kdump搭配使用。

使用crash時,要求調試核心vmlinux在編譯時間帶有-g選項,即帶有調試資訊。

如果沒有指定vmcore,則預設使用即時系統的記憶體來分析。

 

值得一提的是,crash也可以用來分析即時的系統記憶體,是一個很強大的調試工具。

crash使用gdb作為內部引擎,文法類似於gdb,命令的使用說明可以用<cmd> help來查看。

使用crash需要安裝crash工具包和核心調試資訊包:

crash

kernel-debuginfo-common

kernel-debuginfo

  crash使用

 

Analyze Linux crash dump data or a live system.

crash [OPTION] NAMELIST MEMORY-IMAGE      (dumpfile form)

crash [OPTION] [NAMELIST]                                   (live system form)

 

使用crash來調試vmcore,至少需要兩個參數:

NAMELIST:未壓縮的核心映像檔案vmlinux,預設位於/usr/lib/debug/lib/modules/$(uname -r)/vmlinux,由

核心調試資訊包提供。

MEMORY-IMAGE:記憶體轉儲檔案vmcore,預設位於/var/crash/%HOST-%DATE/vmcore,由kdump產生。

例如:# crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux   /var/crash/%HOST-%DATE/vmcore

 

(1) 錯誤類型

首先可以在vmcore-dmesg.txt中先查看錯誤類型,如:

1. divide error: 0000 [#1] SMP,除數為0造成核心崩潰,由1號CPU觸發。

2. BUG: unable to handle kernel NULL pointer dereference at 000000000000012c,引用null 指標。

這樣一來就能知道引發核心崩潰的錯誤類型。

 

(2) 錯誤地點

RIP為造成核心崩潰的指令,Call Trace為函數調用棧,通過RIP和Call Trace可以確定函數的調用路徑,以及在

哪個函數中的哪條指令引發了錯誤。

 

例如RIP為:[<ffffffff812cdb54>] ? tcp_enter_loss+0x1d3/0x23b

[<ffffffff812cdb54>]是指令在記憶體中的虛擬位址。

tcp_enter_loss是函數名(symbol)。

0x1d3是這條指令相對於tcp_enter_loss入口的位移,0x23b是函數編譯成機器碼後的長度。

這樣一來就能確定在哪個函數中引發了錯誤,以及錯誤的大概位置。

 

Call Trace為函數的調用棧,是從下往上看的。可以用來分析函數的調用關係。

 

(3) crash基本輸出

# crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux   /var/crash/%HOST-%DATE/vmcore

      KERNEL: /usr/lib/debug/lib/modules/2.6.32-358.el6.x86_64/vmlinux    DUMPFILE: vmcore  [PARTIAL DUMP]        CPUS: 12        DATE: Fri Sep 19 16:47:01 2014      UPTIME: 7 days, 06:37:46LOAD AVERAGE: 0.19, 0.05, 0.01       TASKS: 282    NODENAME: localhost.localdomain     RELEASE: 2.6.32-358.el6.x86_64     VERSION: #1 SMP Tue Oct 29 10:18:21 CST 2013     MACHINE: x86_64  (1999 Mhz)      MEMORY: 48 GB       PANIC: "Oops: 0002 [#1] SMP " (check log for details)         PID: 0     COMMAND: "swapper"        TASK: ffffffff81a8d020  (1 of 12)  [THREAD_INFO: ffffffff81a00000]         CPU: 0       STATE: TASK_RUNNING (PANIC)

這些基本輸出資訊簡單明了,可由sys命令觸發。

 

(4) crash常用命令

bt:列印函數調用棧,displays a task's kernel-stack backtrace,可以指定進程號bt <pid>。

log:列印系統訊息緩衝區,displays the kernel log_buf contents,如log | tail -n 30。

ps:顯示進程的狀態,>表示活躍的進程,如ps | grep RU。

sys:顯示系統概況。

kmem -i:顯示記憶體使用量資訊。

dis <addr>:對給定地址進行反組譯碼。

 

exception RIP即為造成錯誤的指令。

關於log命令:

核心首先把訊息列印到核心態的ring buffer,使用者態的klogd負責讀取並轉寄給syslogd,讓它記錄到磁碟。

在核心崩潰時,可能無法把訊息記錄到磁碟,但是ring buffer中一般會有記錄。所以log命令有時候能查看

到系統日誌中所缺失的資訊。

 

(5) 結構體和變數

查看結構體中所有成員的值,例如:

# ps | grep RU

>     0      0   0  ffffffff81a8d020  RU   0.0       0      0  [swapper]

# struct task_struct ffffffff81a8d020

struct task_struct {  state = 0,   stack = 0xffffffff81a00000,   usage = {    counter = 2  },   flags = 2097408, 

顯示整個結構體的定義:

# struct task_struct

struct task_struct {    volatile long int state;    void *stack;    atomic_t usage;    unsigned int flags;

顯示整個結構體的定義,以及每個成員的位移:

# struct -o task_struct

struct task_struct {     [0] volatile long int state;     [8] void *stack;    [16] atomic_t usage;    [20] unsigned int flags;    ...

顯示結構體中的成員定義,以及它的位移:

# struct task_struct.pid

struct task_struct {  [1192] pid_t pid;}

顯示結構體中成員的值:

# struct task_struct.pid ffffffff81a8d020

  pid = 0

查看全域變數的值:

# p sysctl_tcp_rmem

sysctl_tcp_rmem = $4 =  {40960, 873800, 41943040}

 

查看percpu全域變數(加首碼per_cpu_):

# p per_cpu__irq_stat

PER-CPU DATA TYPE:  irq_cpustat_t per_cpu__irq_stat; // 變數類型的聲明PER-CPU ADDRESSES:  [0]: ffff880028216540 // 0號CPU對應變數的地址  [1]: ffff880645416540  ...

查看0號CPU對應變數的值:

# struct irq_cpustat_t ffff880028216540

struct irq_cpustat_t {  __softirq_pending = 0,   __nmi_count = 4780195,   irq0_irqs = 148,   ...

 

(6) 反組譯碼和源碼行

反組譯碼:

# dis ffffffffa021ba91 // 反組譯碼一條指令

# dis -l probe_2093+497 10 // 反組譯碼從某個地址開始的10條指令

對於核心中的符號:

# sym tcp_v4_do_rcv // 通過symbol,顯示虛擬位址和源碼位置

# sym ffffffff8149f930 // 通過虛擬位址,顯示symbol和源碼位置

 

對於模組中的符號:

需要先載入相應的模組進來,才能顯示符號對應的源碼:

# mod // 查看模組

# mod -s module /path/to/module.ko // 載入模組

# sym symbol // 顯示符號對應的模組源碼,也可以用virtual address

 

(7) 修改記憶體

提供動態修改運行中核心的功能,以供調試,但是RHEL和CentOS上不允許。

wr:modifies the contents of memory.

wr [-u | -k | -p] [-8 | -16 | -32 | -64] [address | symbol] value

 

使用例子:

# p sysctl_tcp_timestamps

sysctl_tcp_timestamps = $3 = 1

# wr sysctl_tcp_timestamps 0

wr: cannot write to /dev/crash!


我勒個擦,/dev/crash的檔案屬性是rw,但是crash_fops中並沒有提供寫函數,所以還是唯讀。

這個功能很有用,但被RHEL和CentOS禁止了,所以如需動態修改運行核心還是用systemtap吧。

  Reference

 

[1]. http://www.ibm.com/developerworks/cn/linux/l-cn-kdump1/

[2]. http://www.ibm.com/developerworks/cn/linux/l-cn-kdump2/

[3]. http://www.ibm.com/developerworks/cn/linux/l-cn-kdump3/

[4]. http://www.ibm.com/developerworks/cn/linux/l-cn-kdump4/

[5]. http://www.ibm.com/developerworks/cn/linux/l-cn-dumpanalyse/

[6]. http://people.redhat.com/anderson/crash_whitepaper/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.