本文是做成了一个系列,主要是考虑到合成一篇文章太长了,不一定能看得完。而且各个有关Kdump机制的部分互不冲突,因此各位可以选择性阅读。


Kdump概述

Kdump 的概念出现在 2005 左右,是迄今为止最可靠的内核转存机制,已经被主要的 linux™ 厂商选用。
kdump是在系统崩溃、死锁或者死机的时候用来转储内存运行参数的一个工具和服务

Kdump相关名词定义

  • 生产内核:第一个运行的内核(正常的系统运行内核)
  • 捕获内核:第二个运行的内核(系统异常时,会启动捕获内核,用以对生产内核下的内存进行收集和转存)
  • ramdisk:这里讲的ramdisk实际上就是把一段内存假设为一个硬盘驱动器(使用ramdisk作为文件系统可以大幅提高读写速度)
  • ELF文件:这里讲的是内核分析出内存的使用和分布等情况,然后把这些信息综合起来生成一个ELF头文件保存起来。

Kdump实现原理

Kdump 的实现可以分为两个部分:内核用户工具。内核提供机制,用户工具在这些机制上实现各种转储策略。内核机制对用户工具的接口是一个系统调用:kexec_load(),它被用于加载捕获内核和传递一些相关信息。
Kdump 是一种先进的基于 kexec 的内核崩溃转储机制,用来捕获kernel crash(内核崩溃)的时候产生的crash dump。当内核产生错误(系统崩溃、死锁或者死机)时,kdump会将内存导出为vmcore保存到磁盘。
Kdump的实现依赖于Kexec,下面分别介绍Kexec、Kdump这两个机制:


Kexec机制

Kexec是基于kexec机制工作的,因此先了解一下Kexec。
kexec是一个快速启动机制,允许通过已经运行的内核的上下文启动一个Linux内核,不需要经过BIOS。(BIOS可能会消耗很多时间,特别是带有众多数量的外设的大型服务器。这种办法可以为经常启动机器的开发者节省很多时间。)

Kexec的实现包括2个组成部分:

一是内核空间的系统调用:kexec_load(),负责在生产内核(production kernel 或 first kernel)启动时将捕获内核(capture kernel或sencond kernel)加载到指定地址。
二是用户空间的工具kexec-tools,他将捕获内核的地址传递给生产内核,从而在系统崩溃的时候能够找到捕获内核的地址并运行。没有kexec就没有kdump。先有kexec实现了在一个内核中可以启动另一个内核,才让kdump有了用武之地。

内核空间:kexec_load()
kexec 在 kernel 里以一个系统调用 kexec_load()
的形式提供给用户。这个系统调用主要用来把另一个内核和其 ramdisk 加载到当前内核中。在 kdump
中,捕获内核只能使用事先预留的一小段内存。生产内核的内存镜像会被以 /proc/vmcore 的形式提供给用户。这是一个 ELF
格式的方件,它的头是由用户空间工具 kexec 生成并传递来的。在系统崩溃时,系统最后会调用
machine_kexec()。这通常是一个硬件相关的函数。它会引导捕获内核,从而完成 kdump 的过程。

用户空间:kexec-tools
kdump 的很大一部分工作都是在用户空间内完成的。与 kexec
相关的集中在一个叫“kexec-tools”的工具中的“kexec”程序中。该程序主要是为调用 kexec_load()
收集各种信息,然后调用之。这些信息主要包括 purgatory 的入口地址,还有一组由 struct kexec_segment
描述的信息。


Kdump机制

kdump机制的实现需要两个不同目的的内核,生产内核捕获内核。生产内核是捕获内核服务的对像。捕获内核会在生产内核崩溃时启动起来,与相应的ramdisk一起组建一个微环境,用以对生产内核下的内存进行收集和转存。
第一个内核保留了内存的一部分给第二内核启动用。由于kdump利用kexec启动捕获内核,绕过了 BIOS,所以第一个内核的内存得以保留。这是内核崩溃转储的本质。

为了在生产内核崩溃时能顺利启动捕获内核,捕获内核以及它的ramdisk是事先放到生产内核的内存中的

生产内核的内存是通过/proc/vmcore这个文件交给捕获内核的。为了生成它,用户工具在生产内核中分析出内存的使用和分布等情况,然后把这些信息综合起来生成一个ELF头文件保存起来。捕获内核被引导时会被同时传递这个ELF文件头的地址,通过分析它,捕获内核就可以生成出/proc/vmcore。有了/proc/vmcore这个文件,捕获内核的ramdisk中的脚本就可以通过通常的文件读写和网络来实现各种策略了。

注意,在启动时,kdump保留了一定数量的重要的内存,为了计算系统需要的真正最小内存,加上kdump使用的内存数量,以决定真正的最小内存的需求。


Kexec和Kdump的设计区别

Kexec的设计是用新内核去覆盖原内核位置;

Kdump的设计是预留一块内存来加载第二个内核(和相关数据),发送Crash后第二个内核在原位置运行(不然就达不到相关目的了),收集第一个内核的相关内存信息。

具体可以通过下图去介绍两种设计的区别:

centos kdump设置 centos7 kdump_crash


Kdump的应用场景

例如,执行某个驱动时莫名其妙的系统就没有反应了,没有任何的异常信息打印,查看日志也是什么异常信息都没有记录,记录的只是启动后的日志,通过监控系统发现在系统在没有反应前cpu、内存、负载、流量都很正常,就是突然没有响应了,排查起问题来很难搞。
这时候就可以通过Kdump大展身手!这是一个可信赖的内核崩溃转储工具。

使用Kdump的目的:

  1. 明白内核崩溃的大致原因;
  2. 可以对内核崩溃的原因做更细致的分析;

Kdump执行流程

  1. First kernel(生产内核)正常运行;
  2. 运行过程中,系统出现异常(也可以是模拟通过sysrq触发panic);
  3. 在系统崩溃时,系统最后会调用 machine_kexec(),触发并启动Sencond kernel(捕获内核),传递ELF头文件的地址;
  4. 捕获内核与相应的ramdisk一起组建一个微环境,获取ELF头文件的地址,并生成出/proc/vmcore文件;
  5. 捕获内核的ramdisk中的脚本开始执行,将/proc/vmcore文件中的数据通过文件读写和网络来实现对生产内核下的内存进行收集和转存。
  6. 通过gdb、crash等工具,对收集到的vmcore文件镜像分析

结合下面的图片,可以更好的理解整个流程:

centos kdump设置 centos7 kdump_kdump_02


参考:
Linux内核调试之kdumpkdump 简介 & 配置、触发等移植Kdump至嵌入式ARM64环境Kdump 原理探秘kexeckdump和crash的配置方法与内核故障原因分析(一)使用crash分析linux内核崩溃转储文件vmcorekdump在Debian / Fedora / CentOS下的配置