天天看點

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

一、linux:

當程式運作的過程中異常終止或崩潰,作業系統會将程式當時的記憶體狀态記錄下來,儲存在一個檔案中,這種行為就叫做Core Dump(“核心轉儲”)。可以認為 core dump 是“記憶體快照”,但實際上,除了記憶體資訊之外,還有些關鍵的程式運作狀态也會同時dump 下來,例如寄存器資訊(包括程式指針、棧指針等)、記憶體管理資訊、其他處理器和作業系統狀态和資訊。core dump對于程式設計人員診斷和調試程式是非常有幫助的,因為對于有些程式錯誤是很難重制的,例如指針異常,而 core dump 檔案可以再現程式出錯時的情景。

Core Dump 如何産生

上面說當程式運作過程中異常終止或崩潰時會發生core dump,但沒說什麼具體的情景程式會發生異常終止或崩潰,例如我們使用 ​

​kill -9​

​ 指令殺死一個程序會發生 core dump 嗎?實驗證明是不能的,那麼什麼情況會産生呢?

Linux 中信号是一種異步事件處理的機制,每種信号對應有其預設的操作,你可以在 ​​這裡​​ 檢視 Linux 系統提供的信号以及預設處理。預設操作主要包括忽略該信号(Ingore)、暫停程序(Stop)、終止程序(Terminate)、終止并發生core dump(core)等。如果我們信号均是采用預設操作,那麼,以下列出幾種信号,它們在發生時會産生 core dump:

Signal Action Comment
SIGQUIT Core Quit from keyboard
SIGILL Illegal Instruction
SIGABRT Abort signal from ​​abort​​
SIGSEGV Invalid memory reference
SIGTRAP Trace/breakpoint trap

當然不僅限于上面的幾種信号。這就是為什麼我們使用 ​

​Ctrl+z​

​ 來挂起一個程序或者 ​

​Ctrl+C​

​ 結束一個程序均不會産生 core dump,因為前者會向程序發出 SIGTSTP 信号,該信号的預設操作為暫停程序(Stop Process);後者會向程序發出SIGINT 信号,該信号預設操作為終止程序(Terminate Process)。同樣上面提到的 ​

​kill -9​

​ 指令會發出 SIGKILL 指令,該指令預設為終止程序。而如果我們使用 ​

​Ctrl+\​

​ 來終止一個程序,會向程序發出 SIGQUIT 信号,預設是會産生 core dump 的。還有其它情景會産生 core dump, 如:程式調用 ​

​abort()​

​ 函數、訪存錯誤、非法指令等等。

下面舉兩個例子來說明:

  • 終端下比較 ​

    ​Ctrl+C​

    ​ 和 ​

    ​Ctrl+\​

    ​:
  • 小程式産生 core dump
·       guohailin@guohailin:~$ sleep 10        #使用sleep指令休眠 10 s      
·       ^C                           #使用 Ctrl+C 終止該程式,不會産生 core dump      
·       guohailin@guohailin:~$ sleep 10      
·       ^\Quit (core dumped)                #使用 Ctrl+\ 退出程式,會産生 core dump      
·       guohailin@guohailin:~$ ls         #多出下面一個 core 檔案      
·       -rw-------  1 guohailin guohailin 335872 10月 22 11:31 sleep.core.21990      
·       #include <stdio.h>      
·      
·       int main()      
·       {      
·           int *null_ptr = NULL;      
·           *null_ptr = 10;            //對空指針指向的記憶體區域寫,會發生段錯誤      
·           return 0;      
·       }      
·       #編譯執行      
·       guohailin@guohailin:~$ ./a.out      
·       Segmentation fault (core dumped)      
·       guohailin@guohailin:~$ ls      #多出下面一個 core 檔案      
·       -rw-------  1 guohailin guohailin 200704 10月 22 11:35 a.out.core.22070      

Linux 下打開 Core Dump

我使用的 Linux 發行版是 Ubuntu 13.04,設定生成 core dump 檔案的方法如下:

  • 打開 core dump 功能
  • 在終端中輸入指令 ​

    ​ulimit -c​

    ​ ,輸出的結果為 0,說明預設是關閉 core dump 的,即當程式異常終止時,也不會生成 core dump 檔案。
  • 我們可以使用指令 ​

    ​ulimit -c unlimited​

    ​ 來開啟 core dump 功能,并且不限制 core dump 檔案的大小; 如果需要限制檔案的大小,将 unlimited 改成你想生成 core 檔案最大的大小,注意機關為 blocks(KB)。
  • 用上面指令隻會對目前的終端環境有效,如果想需要永久生效,可以修改檔案 ​

    ​/etc/security/limits.conf​

    ​檔案,關于此檔案的設定參看 ​​這裡​​ 。增加一行:
  • 修改 core 檔案儲存的路徑
  • 預設生成的 core 檔案儲存在可執行檔案所在的目錄下,檔案名就為 ​

    ​core​

    ​。
  • 通過修改 ​

    ​/proc/sys/kernel/core_uses_pid​

    ​ 檔案可以讓生成 core 檔案名是否自動加上 pid 号。

    例如 ​

    ​echo 1 > /proc/sys/kernel/core_uses_pid​

    ​ ,生成的core 檔案名将會變成 ​

    ​core.pid​

    ​,其中 pid 表示該程序的 PID。
  • 還可以通過修改 ​

    ​/proc/sys/kernel/core_pattern​

    ​ 來控制生成 core 檔案儲存的位置以及檔案名格式。

    例如可以用 ​

    ​echo "/tmp/corefile-%e-%p-%t" >/proc/sys/kernel/core_pattern​

    ​ 設定生成的 core 檔案儲存在 “/tmp/corefile” 目錄下,檔案名格式為 “core-指令名-pid-時間戳”。​​這裡​​ 有更多詳細的說明!
·       # /etc/security/limits.conf      
·       #      
·       #Each line describes a limit for a user in the form:      
·       #      
·       #<domain>   <type>   <item>   <value>      
·           *          soft     core   unlimited      

使用 gdb 調試 Core 檔案

産生了 core 檔案,我們該如何使用該 Core 檔案進行調試呢?Linux 中可以使用 GDB 來調試 core 檔案,步驟如下:

  • 首先,使用 gcc 編譯源檔案,加上 ​

    ​-g​

    ​ 以增加調試資訊;
  • 按照上面打開 core dump 以使程式異常終止時能生成 core 檔案;
  • 運作程式,當core dump 之後,使用指令 ​

    ​gdb program core​

    ​ 來檢視 core 檔案,其中 program 為可執行程式名,core 為生成的 core 檔案名。

下面用一個簡單的例子來說明:

#include <stdio.h>      
int func(int *p)      
{      
int y = *p;      
return y;      
}      
int main()      
{      
int *p = NULL;      
return func(p);      
}      

編譯加上調試資訊,運作之後core dump,使用 gdb 檢視 core 檔案。

guohailin@guohailin:~$ gcc core_demo.c -o core_demo -g      
guohailin@guohailin:~$ ./core_demo      
Segmentation fault (core dumped)      
guohailin@guohailin:~$ gdb core_demo core_demo.core.24816      
...      
Core was generated by './core_demo'.      
Program terminated with signal 11, Segmentation fault.      
#0  0x080483cd in func (p=0x0) at core_demo.c:5      
5       int y = *p;      
(gdb)  where      
#0  0x080483cd in func (p=0x0) at core_demo.c:5      
#1  0x080483ef in main () at core_demo.c:12      
(gdb) info frame      
Stack level 0, frame at 0xffd590a4:      
eip = 0x80483cd in func (core_demo.c:5); saved eip 0x80483ef      
called by frame at 0xffd590c0      
source language c.      
Arglist at 0xffd5909c, args: p=0x0      
Locals at 0xffd5909c, Previous frame's sp is 0xffd590a4      
Saved registers:      
ebp at 0xffd5909c, eip at 0xffd590a0      
(gdb)      

從上面可以看出,我們可以還原 core_demo 執行時的場景,并使用 ​

​where​

​ 可以檢視目前程式調用函數棧幀,還可以使用 gdb 中的指令檢視寄存器,變量等資訊。

舉例快速上手:

[root@yunji tmp]# sleep 1000

[root@yunji ~]# ps -ef|grep sleep

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

 在‘sleep 1000’指令下,輸入:control+\,顯示:

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

 ^\退出(core)

檢視有無core檔案生成:

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

 [root@yunji tmp]# gdb program corefile-sleep-31318-1628152235

GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
program: 沒有那個檔案或目錄.
[New LWP 31318]
Missing separate debuginfo for the main executable file
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/bb/e03535757d35ca69c622cb8d59501fe8db932f
Core was generated by `sleep 1000'.
Program terminated with signal 3, Quit.
#0  0x00007f56af7908d0 in ?? ()
(gdb)
      

 問題:顯示了沒有程序。

二、mac:

開啟coredump:

%ulimit -c unlimited

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

  檢視程序:

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

不指定目錄,core檔案均存在/cores 目錄中。

cd /cores

ls

運作 lldb -c “core檔案的名稱”

lldb -c core.2112

warning: (x86_64) /cores/core.21126 load command 1188 LC_SEGMENT_64 has a fileoff (0x23aee5a5c8) that extends beyond the end of the file (0x95799000), ignoring this section

運作bt就可以看到程式崩潰時的堆棧資訊了。

三、windows:

在 Windows 10 上,每次發生崩潰時,系統都會建立一個“轉儲”檔案,其中包含錯誤發生時的記憶體資訊,可以幫助确定問題的原因。

“.dmp”檔案包括停止錯誤消息、出現問題時加載的驅動程式清單、核心、處理器和程序詳細資訊,以及其他取決于您使用的轉儲檔案類型的資訊。

Windows 10自動建立的轉儲檔案可使用Microsoft WinDbg 工具(Windows 調試核心模式和使用者模式代碼、檢查處理器系統資料庫和分析故障轉儲工具)調試。

1、安裝 WinDbg步驟:

1)打開您喜歡的浏覽器。

​​2)打開WinDbg下載下傳頁面​​。

3)單擊擷取(或安裝/打開)按鈕。

4)單擊打開按鈕。

5)單擊安裝按鈕。

完成這些步驟後,将安裝該應用程式,并可通過“開始”菜單使用它。

2、分析轉儲檔案

要打開和分析由 Windows 10 崩潰建立的轉儲檔案步驟:

1)打開開始。

2)搜尋WinDbg,右鍵單擊頂部結果,選擇以管理者身份運作選項。​​

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

​​

3)單擊檔案菜單。

4)單擊開始調試。

5)選擇打開油槽檔案選項。

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

6)從檔案夾位置選擇轉儲檔案 - 例如,​

​%SystemRoot%\Minidump​

​.

7)單擊打開按鈕。

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

8)檢查進度條,直到它加載轉儲檔案(這可能需要一段時間)。

9)在運作指令中鍵入以下指令并按Enter 鍵:

​!analyze -v​

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

快速提示:您還可以單擊!analyze -v連結(如果在加載轉儲檔案後可用)從主區域可用。

10)檢查進度條直到分析完成(這可能需要很長時間,具體取決于資料大小)。

完成這些步驟後,應用程式将傳回轉儲檔案分析,然後您可以檢視這些分析以确定問題的原因以幫助您解決問題。

資訊會因問題而異。例如,此測試轉儲檔案顯示藍屏當機 (BSoD)(也稱為錯誤檢查)的資訊。

結果指出這是一個帶有“e2”錯誤代碼的手動啟動的崩潰,這是正确的,因為出于本指南的目的,我們使用​​這些指令來強制 BSoD​​。WinDbg 甚至出色地用任何人都能了解的語言描述了崩潰(使用者手動啟動了此崩潰轉儲)。

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

當繼續檢視轉儲檔案時,您還會發現更多資訊,例如“FAILURE_BUCKET_ID”和“MODULE_NAME”,它們可以指出導緻問題的原因。

Linux 、Mac及windows上故障轉儲檔案(core dump)擷取方法

繼續閱讀