>시스템 튜토리얼 >리눅스 >Linux 커널 충돌 감지 도구 Kdump

Linux 커널 충돌 감지 도구 Kdump

王林
王林앞으로
2024-01-03 19:25:421239검색
소개 kdump는 손상된 Linux 커널 덤프를 얻는 한 가지 방법이지만 사용법과 내부를 설명하는 문서를 찾는 것이 약간 어려울 수 있습니다. 이 기사에서는 kdump의 기본 사용법과 kdump/kexec가 커널에서 어떻게 구현되는지 연구합니다.

kexec는 첫 번째 커널 컨텍스트에서 두 번째 커널로 부팅하는 데 도움이 되는 Linux 커널 간 부트로더입니다. kexec는 BIOS 또는 펌웨어 단계를 우회하여 첫 번째 코어를 종료하고 두 번째 코어로 점프합니다. 따라서 BIOS 단계가 없으면 재부팅 속도가 더 빨라집니다.

kdump는 kexec 애플리케이션과 함께 사용할 수 있습니다. 예를 들어 첫 번째 커널이 충돌하고 두 번째 커널이 시작되면 두 번째 커널은 첫 번째 커널의 메모리 덤프를 복사하는 데 사용되며, 이는 gdb 및 crash 충돌의 원인입니다. (이 기사에서는 현재 실행 중인 커널을 "첫 번째 커널", kexec 로 실행 중인 커널을 "두 번째 커널", 현재 커널이 충돌할 때 실행 중인 커널을 의미하는 "캡처 커널"이라는 용어를 사용합니다.)

kexec 메커니즘에는 커널과 사용자 공간에 구성 요소가 있습니다. 커널은 kexec 재시작 기능을 위한 여러 시스템 호출을 제공합니다. kexec-tools라는 사용자 공간 도구는 이러한 호출을 사용하고 "두 번째 커널"을 로드하고 부팅하기 위한 실행 파일을 제공합니다. 일부 배포판은 다양한 덤프 대상 구성의 덤프를 캡처하고 저장하는 데 도움이 되는 래퍼를 kexec-tools에 추가합니다. 이 기사에서는 업스트림 kexec 도구와 배포판별 kexec-tools 코드 간의 혼동을 피하기 위해 distro-kexec-tools라는 도구를 사용하겠습니다. 내 예제에서는 Fedora Linux 배포판을 사용합니다.

Fedora kexec-tools 도구

dnf install kexec-tools 명령을 사용하여 Fedora 시스템에 fedora-kexec-tools를 설치합니다. fedora-kexec-tools를 설치한 후 systemctl start kdump 명령을 실행하여 kdump 서비스를 시작할 수 있습니다. 이 서비스가 시작되면 대상 위치에 마운트하고 vmcore를 보관할 리소스와 vmcore를 대상 위치에 복사 및 덤프하는 명령이 포함된 루트 파일 시스템(initramfs)을 생성합니다. 그런 다음 서비스는 커널이 충돌하는 경우 실행될 수 있도록 커널과 initramfs를 충돌된 커널 영역 내의 적절한 위치에 로드합니다.

Fedora 래퍼는 두 가지 사용자 프로필을 제공합니다:

/etc/kdump.conf는 수정 후 다시 빌드해야 하는 구성 매개변수를 지정합니다. 예를 들어 덤프 대상을 로컬 디스크에서 NFS 탑재 디스크로 변경하는 경우 Capture Kernel에서 로드한 NFS 관련 커널 모듈이 필요합니다.
/etc/sysconfig/kdump는 수정 후 initramfs를 다시 빌드할 필요가 없는 구성 매개변수를 지정합니다. 예를 들어, "캡처 커널"에 전달된 명령줄 매개변수만 수정해야 하는 경우 initramfs를 다시 빌드할 필요가 없습니다.
kdump 서비스가 시작된 후 커널이 실패하면 "캡처 커널"이 수행되어 initramfs에서 vmcore 저장 프로세스를 추가로 수행한 다음 안정적인 커널로 재부팅됩니다.

kexec-tools 도구

kexec-tools의 소스 코드를 컴파일하고 kexec라는 실행 파일을 얻습니다. 이 시조 실행 파일은 "두 번째 커널"을 로드 및 실행하거나 커널이 충돌할 때 실행될 수 있는 "캡처 커널"을 로드하는 데 사용할 수 있습니다.

"두 번째 커널"을 로드하는 명령:

으아아아

--reuse-command 매개변수는 "첫 번째 커널"과 동일한 명령줄을 사용한다는 의미입니다. initramfs를 전달하려면 --initrd를 사용하세요. -l은 kexec 애플리케이션 자체에서 실행할 수 있는 "두 번째 커널"을 로드하고 있음을 나타냅니다(kexec -e). -l로 로드된 커널은 커널 패닉 시 실행할 수 없습니다. 커널 충돌 시 실행될 수 있는 "캡처 커널"을 로드하려면 -l 대신 -p 인수를 전달해야 합니다.

캡처 커널을 로드하는 명령:

으아아아

echo c > /pros/sysrq-trigger는 테스트를 위해 커널을 충돌시키는 데 사용될 수 있습니다. kexec-tools에서 제공하는 옵션에 대한 자세한 내용은 man kexec를 참조하세요. 다음 섹션으로 넘어가기 전에 kexec_dump 데모를 살펴보세요.


kdump: 엔드투엔드 스트리밍

아래 사진은 흐름도를 보여줍니다. crashkernel의 메모리는 "첫 번째 커널"을 부팅하는 동안 캡처 커널용으로 예약되어야 합니다. 커널 명령줄에서 crashkernel=Y@X를 전달할 수 있습니다. 여기서 @X는 선택 사항입니다. crashkernel=256M은 대부분의 x86_64 시스템에서 작동합니다. 그러나 crashkernel에 적합한 메모리를 선택하는 것은 커널 및 initramfs의 크기는 물론 initramfs에 포함된 모듈 및 애플리케이션의 메모리 요구 사항과 같은 여러 요소에 따라 달라집니다. 실행 시간. 충돌 커널 매개변수를 전달하는 더 많은 방법은 커널 매개변수 설명서를 참조하세요.
Kdump 检查 Linux 内核崩溃!

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 或开始地址。
ELF 程序头

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 的表示:
Kdump 检查 Linux 内核崩溃!

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 note

Crash notes 是每个 CPU 中用于在系统崩溃的情况下存储 CPU 状态的区域;它有关于当前 PID 和 CPU 寄存器的信息。

vmcoreinfo

该 note 段具有各种内核调试信息,如结构体大小、符号值、页面大小等。这些值由捕获内核解析并嵌入到 /proc/vmcore 中。 vmcoreinfo 主要由 makedumpfile 应用程序使用。在 Linux 内核,include/linux/kexec.h 宏定义了一个新的 vmcoreinfo。 一些示例宏如下所示:

  • VMCOREINFO_PAGESIZE()
  • VMCOREINFO_SYMBOL()
  • VMCOREINFO_SIZE()
  • VMCOREINFO_STRUCT_SIZE()
makedumpfile

vmcore 中的许多信息(如可用页面)都没有用处。makedumpfile 是一个用于排除不必要的页面的应用程序,如:

  • 填满零的页面;
  • 没有私有标志的缓存页面(非专用缓存);
  • 具有私有标志的缓存页面(专用缓存);
  • 用户进程数据页;
  • 可用页面。

此外,makedumpfile 在复制时压缩 /proc/vmcore 的数据。它也可以从转储中删除敏感的符号信息; 然而,为了做到这一点,它首先需要内核的调试信息。该调试信息来自 VMLINUX 或 vmcoreinfo,其输出可以是 ELF 格式或 kdump 压缩格式。

典型用法:

# makedumpfile -l --message-level 1 -d 31 /proc/vmcore makedumpfilecore

详细信息请参阅 man makedumpfile。

kdump 调试

新手在使用 kdump 时可能会遇到的问题:

kexec -p kernel_image 没有成功

检查是否分配了崩溃内存。

  • cat /sys/kernel/kexec_crash_size 값은 0이 아니어야 합니다.
  • cat /proc/iomem | grep "Crash kernel" 할당된 범위가 있어야 합니다.
  • 할당되지 않은 경우 명령줄에 올바른 crashkernel= 매개변수를 전달하세요.
  • 표시되지 않으면 -d 인수를 kexec 명령에 전달하고 출력을 kexec-tools 메일링 리스트로 보냅니다.
"첫 번째 커널"의 마지막 메시지 이후 콘솔에서 아무 것도 볼 수 없습니다(예: "안녕")
  • kexec -e 다음에 kexec -l kernel_image 명령이 작동하는지 확인하세요.
  • 지원되는 아키텍처 또는 시스템별 옵션이 누락되었을 수 있습니다.
  • 연옥의 SHA 확인이 실패했을 수도 있습니다. 아키텍처가 연옥의 콘솔을 지원하지 않으면 디버깅이 어려울 수 있습니다.
  • "두 번째 커널"이 이미 충돌했을 수도 있습니다.
  • 시스템의 earlycon 또는 earlyprintk 옵션을 "두 번째 커널" 명령줄에 전달하세요.
  • kexec-tools 메일링 리스트를 사용하여 첫 번째 커널을 공유하고 커널의 dmesg 로그를 캡처하세요.
리소스 fedora-kexec-tools
  • GitHub 저장소: git://pkgs.fedoraproject.org/kexec-tools
  • 메일 목록: [이메일 보호됨]
  • 설명: 사양 파일과 스크립트는 다양한 사용자 시나리오에서 kexec-tools를 자동화할 수 있도록 사용자에게 친숙한 명령과 서비스를 제공합니다.
kexec-도구
  • GitHub 저장소: git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
  • 메일 목록: [이메일 보호됨]
  • 설명: 커널 시스템 호출을 사용하고 사용자 명령 kexec를 제공합니다.
Linux 커널
  • GitHub 저장소: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  • 메일 목록: [이메일 보호됨]
  • 설명: kexec_load(), kexec_file_load(), 재부팅() 시스템 호출과 machine_kexec() 및 machine_crash_shutdown()과 같은 아키텍처별 코드를 구현합니다.
Makedumpfile
  • GitHub 저장소: git://git.code.sf.net/p/makedumpfile/code
  • 메일 목록: [이메일 보호됨]
  • 설명: 덤프 파일에서 불필요한 구성 요소를 압축하고 필터링합니다.

(제목: 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를 홍보하고 있습니다.


위 내용은 Linux 커널 충돌 감지 도구 Kdump의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 linuxprobe.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제