Kdump 檢查 Linux 核心崩潰!
導讀 | kdump 是獲取崩潰的 核心轉儲的一種方法,但是想找到解釋其使用和內部結構的文件可能有點困難。在本文中,我將研究 kdump 的基本使用方法,和 kdump/kexec 在核心中是如何實現。 |
kexec 是一個 Linux 核心到核心的引導載入程式,可以幫助從第一個核心的上下文引導到第二個核心。kexec 會關閉第一個核心,繞過 BIOS 或韌體階段,並跳轉到第二個核心。因此,在沒有 BIOS 階段的情況下,重新啟動變得更快。
kdump 可以與 kexec 應用程式一起使用 —— 例如,當第一個核心崩潰時第二個核心啟動,第二個核心用於複製第一個核心的記憶體轉儲,可以使用 gdb 和 crash 等工具分析崩潰的原因。(在本文中,我將使用術語“第一核心”作為當前執行的核心,“第二核心” 作為使用 kexec 執行的核心,“捕獲核心” 表示在當前核心崩潰時執行的核心。)
kexec 機制在核心以及使用者空間中都有元件。核心提供了幾個用於 kexec 重啟功能的系統呼叫。名為 kexec-tools 的使用者空間工具使用這些呼叫,並提供可執行檔案來載入和引導“第二核心”。有的發行版還會在 kexec-tools 上新增封裝器,這有助於捕獲並儲存各種轉儲目標配置的轉儲。在本文中,我將使用名為 distro-kexec-tools 的工具來避免上游 kexec 工具和特定於發行版的 kexec-tools 程式碼之間的混淆。我的例子將使用 Fedora Linux 發行版。
使用 dnf install kexec-tools 在 Fedora 機器上安裝 fedora-kexec-tools。在安裝 fedora-kexec-tools 後可以執行 systemctl start kdump 來啟動 kdump 服務。當此服務啟動時,它將建立一個根檔案系統(initramfs),其中包含了要掛載到目標位置的資源,以儲存 vmcore,以及用來複制和轉儲 vmcore 到目標位置的命令。然後,該服務將核心和 initramfs 載入到崩潰核心區域內的合適位置,以便在核心崩潰時可以執行它們。
Fedora 封裝器提供了兩個使用者配置檔案:
/etc/kdump.conf 指定修改後需要重建 initramfs 的配置引數。例如,如果將轉儲目標從本地磁碟更改為 NFS 掛載的磁碟,則需要由“捕獲核心”所載入的 NFS 相關的核心模組。
/etc/sysconfig/kdump 指定修改後不需要重新構建 initramfs 的配置引數。例如,如果只需修改傳遞給“捕獲核心”的命令列引數,則不需要重新構建 initramfs。
如果核心在 kdump 服務啟動之後出現故障,那麼“捕獲核心”就會執行,其將進一步執行 initramfs 中的 vmcore 儲存過程,然後重新啟動到穩定的核心。
編譯 kexec-tools 的原始碼得到了一個名為 kexec 的可執行檔案。這個同名的可執行檔案可用於載入和執行“第二核心”,或載入“捕獲核心”,它可以在核心崩潰時執行。
載入“第二核心”的命令:
# kexec -l kernel.img --initrd=initramfs-image.img –reuse-cmdline
--reuse-command 參數列示使用與“第一核心”相同的命令列。使用 --initrd 傳遞 initramfs。 -l 表明你正在載入“第二核心”,其可以由 kexec 應用程式本身執行(kexec -e)。使用 -l 載入的核心不能在核心崩潰時執行。為了載入可以在核心崩潰時執行的“捕獲核心”,必須傳遞引數 -p 取代 -l。
載入捕獲核心的命令:
# kexec -p kernel.img --initrd=initramfs-image.img –reuse-cmdline
echo c > /pros/sysrq-trigger 可用於使核心崩潰以進行測試。有關 kexec-tools 提供的選項的詳細資訊,請參閱 man kexec。在轉到下一個部分之前,請看這個 kexec_dump 的演示:
下圖展示了流程圖。必須在引導“第一核心”期間為捕獲核心保留 crashkernel 的記憶體。您可以在核心命令列中傳遞 crashkernel=Y@X,其中 @X 是可選的。crashkernel=256M 適用於大多數 x86_64 系統;然而,為崩潰核心選擇適當的記憶體取決於許多因素,如核心大小和 initramfs,以及 initramfs 中包含的模組和應用程式執行時的記憶體需求。有關傳遞崩潰核心引數的更多方法,請參閱 kernel-parameters 文件。
pratyush_f1.png
您可以將核心和 initramfs 映象傳遞給 kexec 可執行檔案,如(kexec-tools)部分的命令所示。“捕獲核心”可以與“第一核心”相同,也可以不同。通常,一樣即可。Initramfs 是可選的;例如,當核心使用 CONFIG_INITRAMFS_SOURCE 編譯時,您不需要它。通常,從第一個 initramfs 中儲存一個不一樣的捕獲 initramfs,因為在捕獲 initramfs 中自動執行 vmcore 的副本能獲得更好的效果。當執行 kexec 時,它還載入了 elfcorehdr 資料和 purgatory 可執行檔案(LCTT 譯註:purgatory 就是一個引導載入程式,是為 kdump 定作的。它被賦予了“煉獄”這樣一個古怪的名字應該只是一種調侃)。 elfcorehdr 具有關於系統記憶體組織的資訊,而 purgatory 可以在“捕獲核心”執行之前執行並驗證第二階段的二進位制或資料是否具有正確的 SHA。purgatory 也是可選的。
當“第一核心”崩潰時,它執行必要的退出過程並切換到 purgatory(如果存在)。purgatory 驗證載入二進位制檔案的 SHA256,如果是正確的,則將控制權傳遞給“捕獲核心”。“捕獲核心”根據從 elfcorehdr 接收到的系統記憶體資訊建立 vmcore。因此,“捕獲核心”啟動後,您將看到 /proc/vmcore 中“第一核心”的轉儲。根據您使用的 initramfs,您現在可以分析轉儲,將其複製到任何磁碟,也可以是自動複製的,然後重新啟動到穩定的核心。
核心提供了兩個系統呼叫:kexec_load() 和 kexec_file_load(),可以用於在執行 kexec -l 時載入“第二核心”。它還為 reboot() 系統呼叫提供了一個額外的標誌,可用於使用 kexec -e 引導到“第二核心”。
kexec_load():kexec_load() 系統呼叫載入一個可以在之後透過 reboot() 執行的新的核心。其原型定義如下:
long kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags);
使用者空間需要為不同的元件傳遞不同的段,如核心,initramfs 等。因此,kexec 可執行檔案有助於準備這些段。kexec_segment 的結構如下所示:
struct kexec_segment { void *buf; /* 使用者空間緩衝區 */ size_t bufsz; /* 使用者空間中的緩衝區長度 */ void *mem; /* 核心的實體地址 */ size_t memsz; /* 實體地址長度 */ };
當使用 LINUX_REBOOT_CMD_KEXEC 呼叫 reboot() 時,它會引導進入由 kexec_load 載入的核心。如果標誌 KEXEC_ON_CRASH 被傳遞給 kexec_load(),則載入的核心將不會使用 reboot(LINUX_REBOOT_CMD_KEXEC) 來啟動;相反,這將在核心崩潰中執行。必須定義 CONFIG_KEXEC 才能使用 kexec,並且為 kdump 定義 CONFIG_CRASH_DUMP。
kexec_file_load():作為使用者,你只需傳遞兩個引數(即 kernel 和 initramfs)到 kexec 可執行檔案。然後,kexec 從 sysfs 或其他核心資訊源中讀取資料,並建立所有段。所以使用 kexec_file_load() 可以簡化使用者空間,只傳遞核心和 initramfs 的檔案描述符。其餘部分由核心本身完成。使用此係統呼叫時應該啟用 CONFIG_KEXEC_FILE。它的原型如下:
long kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char __user * cmdline_ptr, unsigned long flags);
請注意,kexec_file_load 也可以接受命令列,而 kexec_load() 不行。核心根據不同的系統架構來接受和執行命令列。因此,在 kexec_load() 的情況下,kexec-tools 將透過其中一個段(如在 dtb 或 ELF 引導註釋等)中傳遞命令列。
目前,kexec_file_load() 僅支援 x86 和 PowerPC。
當第一個核心崩潰時,在控制權傳遞給 purgatory 或“捕獲核心”之前,會執行以下操作:
- 準備 CPU 暫存器(參見核心程式碼中的 crash_setup_regs());
- 更新 vmcoreinfo 備註(請參閱 crash_save_vmcoreinfo());
- 關閉非崩潰的 CPU 並儲存準備好的暫存器(請參閱 machine_crash_shutdown() 和 crash_save_cpu());
- 您可能需要在此處禁用中斷控制器;
- 最後,它執行 kexec 重新啟動(請參閱 machine_kexec()),它將載入或重新整理 kexec 段到記憶體,並將控制權傳遞給進入段的執行檔案。輸入段可以是下一個核心的 purgatory 或開始地址。
kdump 中涉及的大多數轉儲核心都是 ELF 格式。因此,理解 ELF 程式頭部很重要,特別是當您想要找到 vmcore 準備的問題。每個 ELF 檔案都有一個程式頭:
- 由系統載入器讀取,
- 描述如何將程式載入到記憶體中,
- 可以使用 Objdump -p elf_file 來檢視程式頭。
vmcore 的 ELF 程式頭的示例如下:
# objdump -p vmcore vmcore: file format elf64-littleaarch64 Program Header: NOTE off 0x0000000000010000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0 filesz 0x00000000000013e8 memsz 0x00000000000013e8 flags --- LOAD off 0x0000000000020000 vaddr 0xffff000008080000 paddr 0x0000004000280000 align 2**0 filesz 0x0000000001460000 memsz 0x0000000001460000 flags rwx LOAD off 0x0000000001480000 vaddr 0xffff800000200000 paddr 0x0000004000200000 align 2**0 filesz 0x000000007fc00000 memsz 0x000000007fc00000 flags rwx LOAD off 0x0000000081080000 vaddr 0xffff8000ffe00000 paddr 0x00000040ffe00000 align 2**0 filesz 0x00000002fa7a0000 memsz 0x00000002fa7a0000 flags rwx LOAD off 0x000000037b820000 vaddr 0xffff8003fa9e0000 paddr 0x00000043fa9e0000 align 2**0 filesz 0x0000000004fc0000 memsz 0x0000000004fc0000 flags rwx LOAD off 0x00000003807e0000 vaddr 0xffff8003ff9b0000 paddr 0x00000043ff9b0000 align 2**0 filesz 0x0000000000010000 memsz 0x0000000000010000 flags rwx LOAD off 0x00000003807f0000 vaddr 0xffff8003ff9f0000 paddr 0x00000043ff9f0000 align 2**0 filesz 0x0000000000610000 memsz 0x0000000000610000 flags rwx
在這個例子中,有一個 note 段,其餘的是 load 段。note 段提供了有關 CPU 資訊,load 段提供了關於複製的系統記憶體元件的資訊。
vmcore 從 elfcorehdr 開始,它具有與 ELF 程式頭相同的結構。參見下圖中 elfcorehdr 的表示:
pratyush_f2.png
kexec-tools 讀取 /sys/devices/system/cpu/cpu%d/crash_notes 並準備 CPU PT_NOTE 的標頭。同樣,它讀取 /sys/kernel/vmcoreinfo 並準備 vmcoreinfo PT_NOTE 的標頭,從 /proc/iomem 讀取系統記憶體並準備儲存器 PT_LOAD 標頭。當“捕獲核心”接收到 elfcorehdr 時,它從標頭中提到的地址中讀取資料,並準備 vmcore。
Crash notes 是每個 CPU 中用於在系統崩潰的情況下儲存 CPU 狀態的區域;它有關於當前 PID 和 CPU 暫存器的資訊。
該 note 段具有各種核心除錯資訊,如結構體大小、符號值、頁面大小等。這些值由捕獲核心解析並嵌入到 /proc/vmcore 中。 vmcoreinfo 主要由 makedumpfile 應用程式使用。在 Linux 核心,include/linux/kexec.h 宏定義了一個新的 vmcoreinfo。 一些示例宏如下所示:
- VMCOREINFO_PAGESIZE()
- VMCOREINFO_SYMBOL()
- VMCOREINFO_SIZE()
- VMCOREINFO_STRUCT_SIZE()
vmcore 中的許多資訊(如可用頁面)都沒有用處。makedumpfile 是一個用於排除不必要的頁面的應用程式,如:
- 填滿零的頁面;
- 沒有私有標誌的快取頁面(非專用快取);
- 具有私有標誌的快取頁面(專用快取);
- 使用者程式資料頁;
- 可用頁面。
此外,makedumpfile 在複製時壓縮 /proc/vmcore 的資料。它也可以從轉儲中刪除敏感的符號資訊; 然而,為了做到這一點,它首先需要核心的除錯資訊。該除錯資訊來自 VMLINUX 或 vmcoreinfo,其輸出可以是 ELF 格式或 kdump 壓縮格式。
典型用法:
# makedumpfile -l --message-level 1 -d 31 /proc/vmcore makedumpfilecore
詳細資訊請參閱 man makedumpfile。
新手在使用 kdump 時可能會遇到的問題:
檢查是否分配了崩潰記憶體。
- cat /sys/kernel/kexec_crash_size 不應該有零值。
- cat /proc/iomem | grep "Crash kernel" 應該有一個分配的範圍。
- 如果未分配,則在命令列中傳遞正確的 crashkernel= 引數。
- 如果沒有顯示,則在 kexec 命令中傳遞引數 -d,並將輸出資訊傳送到 kexec-tools 郵件列表。
- 檢查 kexec -e 之後的 kexec -l kernel_image 命令是否工作。
- 可能缺少支援的體系結構或特定機器的選項。
- 可能是 purgatory 的 SHA 驗證失敗。如果您的體系結構不支援 purgatory 中的控制檯,則很難進行除錯。
- 可能是“第二核心”早已崩潰。
- 將您的系統的 earlycon 或 earlyprintk 選項傳遞給“第二核心”的命令列。
- 使用 kexec-tools 郵件列表共享第一個核心和捕獲核心的 dmesg 日誌。
- GitHub 倉庫:git://pkgs.fedoraproject.org/kexec-tools
- 郵件列表:kexec@lists.fedoraproject.org
- 說明:Specs 檔案和 提供了使用者友好的命令和服務,以便 kexec-tools 可以在不同的使用者場景下實現自動化。
- GitHub 倉庫:git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
- 郵件列表:kexec@lists.infradead.org
- 說明:使用核心系統呼叫並提供使用者命令 kexec。
- GitHub 倉庫: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
- 郵件列表:kexec@lists.infradead.org
- 說明:實現了 kexec_load()、kexec_file_load()、reboot() 系統呼叫和特定體系結構的程式碼,例如 machine_kexec() 和 machine_crash_shutdown()。
- GitHub 倉庫: git://git.code.sf.net/p/makedumpfile/code
- 郵件列表:kexec@lists.infradead.org
- 說明:從轉儲檔案中壓縮和過濾不必要的元件。
(題圖:Penguin、 Boot,修改:Opensource.com. CC BY-SA 4.0)
作者簡介:
Pratyush Anand - Pratyush 正在以以為 Linux 核心專家的身份與 Red Hat 合作。他主要負責 Red Hat 產品和上游所面臨的幾個 kexec/kdump 問題。他還處理 Red Hat 支援的 ARM64 平臺周圍的其他核心除錯、跟蹤和效能問題。除了 Linux 核心,他還在上游的 kexec-tools 和 makedumpfile 專案中做出了貢獻。他是一名開源愛好者,並在教育機構舉辦志願者講座,促進了 FOSS。
via:
作者: 譯者: 校對:
本文由 原創編譯, 榮譽推出
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2987800/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 記一次Linux核心崩潰:kdump,crash,vmcoreLinux
- win10查詢崩潰日誌方法 win10怎麼檢視崩潰日誌Win10
- 幽蘭核心崩潰自救記
- 使用 GDB 從崩潰中檢查 Objective C 類(HandleDelegateSource 錯誤訪問)Object
- 配置kdump使用的debug核心
- WWDC 2018:理解崩潰以及崩潰日誌
- iOS應用崩潰了,如何透過崩潰手機連線電腦查詢日誌方法iOS應用崩潰
- APP防崩潰APP
- 崩潰日記
- iOS Crash不崩潰iOS
- app 崩潰的原因APP
- 手把手教你檢視和分析iOS的crash崩潰iOS
- Linux中程式崩潰及重啟的原因詳解!Linux
- 執行緒崩潰為什麼不會導致 JVM 崩潰執行緒JVM
- 益普索:2022年崩潰系統情緒調查
- 檢視Linux核心版本Linux
- IOS 崩潰日誌分析iOS
- MySQL 8.0.11 無故崩潰MySql
- ASR專案實戰-交付過程中遇到的核心崩潰問題
- 記一次 .NET某新能源檢測系統 崩潰分析
- InnoDB 崩潰恢復機制
- 【除錯技巧】Dialog dismiss 崩潰除錯
- iOS 避免常見崩潰(二)iOS
- iOS 避免常見崩潰(一)iOS
- 關於Mozilla崩潰的研究
- 突發:當機崩潰OOMOOM
- 崩潰的一天,西安一碼通崩潰背後的技術問題。
- 記一次 .NET 某新能源材料檢測系統 崩潰分析
- 成都、貴州核酸檢測系統“崩潰”背後的技術原因
- win10 pr崩潰怎麼解決_win10 pr崩潰解決辦法Win10
- iOS開發的底線-崩潰iOS
- iOS開發-stringByEvaluatingJavaScriptFromString導致崩潰iOSJavaScript
- Flutter: BottomNavigationBar + PageView 翻頁時崩潰FlutterNavigationView
- mac版本vscode視窗崩潰crashedMacVSCode
- vs2010除錯崩潰 reflector除錯
- 細剖雅達利大崩潰
- Android 12 “致命”崩潰解決之路Android
- PG崩潰恢復讀取WAL