Kdump简单介绍

什么是Kdump?

Kdump是在系统崩溃、死锁或死机时用来转储内存运行参数的一个工具和服务,是一种新的crash dump捕获机制,用来捕获kernel crash(内核崩溃)的时候产生的crash dump。在第一kernel在运行的时候,系统内部在内存中就已经留存好了给第二kernel(捕获内核)的预留空间(这个预留空间的大小可以自己设定)。在第一kernelcrash的时候,就会进入第二kernel,在第二kernel中执行用户态程序makedumpfile对第一kernel的内存镜像进行裁剪和压缩,最后将第一kernel的vmcore保留在磁盘中并重启。

vmcore分析

对vmcore的分析是分析机器宕机原因的一个十分重要的手段。要分析vmcore,我们现在采用的主要就是crash的分析。在安装了crash以后,我们还需要安装相应的debuginfo等带有符号信息的vmlinx文件才能调试相应的vmcore。
一般我们可以通过安装kernel-debuginfo-common-$(uname -r)相应的包来完成相应文件的安装。但是需要注意的是,我们需要安装kernel-debuginfo-common以及kernel-debuginfo这两个包,而kernel-debuginfo又是依赖于kernel-debuginfo-common的。

但是除了安装上面的包以外,还有一种方法就是自己通过编译源码来获取vmlinux。

而kdump的主要流程如下:

在这里插入图片描述

下面我将会从系统开始的过程来介绍一下kdump的整体过程的:

系统启动阶段

在系统启动的时候,会调用start_kernel这个函数。这个函数就是启动kernel的入口。在系统的启动阶段,这个时候会调用reverse_crashkernel这个函数对crash kernle预留内存。其中,预留内存是根据cmdline给的参数来进行预留的。cmdline中根据crashkernel=Y@X来进行预留的。

crashkernel=Y@X : Y是预留内存的大小;X是偏移。
当机器的内存小于8G的时候,一般不预留;当机器的内存大于8G小于16G的时候,预留125M;当机器的内存大于16G的时候,预留512M

启动kdump服务阶段

在启动kdump服务阶段,这个时候系统已经启动了,systemd在把各项的服务给拉起来。这个时候,systemd会启动kudmp服务。【在kdump的脚本里面有具体的过程】
在启动kdump服务的时候,会按照配置将crash kernel的镜像以及initramfs给加载到预留内存中。

当然,在我们对kdump.conf文件进行了修改以后,我们是需要重启kdump服务来将修改生效的。那么为什么我们需要重启才能生效呢?现在给大家讲一下:
首先,我们知道了我们的normal kernel和crash kernel是隔离的,所有的信息都是需要通过elfcore header(在前面的主要流程里面我漏了elfcorehdr的准备。。。)以及vmcore等信息传递的。那么在修改了配置以后,我们通过命令
touch -m /bin/kdump.conf(这里的具体路径我记得不是很清楚了)
通过touch配置文件,可以更改kdump配置文件的修改时间
然后通过命令:systemctl restart kdump 重启kudmp服务
在源码中,kdump是通过判断配置文件的修改时间来确定是不是修改的,我们这里touch了配置文件,在重启的时候kdump就会重新打包,然后将新包给加载到预留内存中了。

系统崩溃阶段

当系统崩溃的时候,系统会调用panic函数,在这里完成到crash kernel的跳转操作。
下面的代码就是在源码kernel/panic.c文件中的panic函数的部分
在这里插入图片描述
其实真正的跳转的函数在__crash_kexec里面的,让我们来看看__crash_kexec这个函数的乾坤吧:

在这里插入图片描述
在这个函数里面,主要讲讲的就是machine_kexec:
进入这个函数,在x86的机器下,会执行一个叫做relocate_kernel的函数,这个函数就是执行一个.S文件 (这是一个汇编代码),在这里完成跳转到crash kernel的工作。但是如果这一系列操作出现了错误,导致了跳转到crash kernel出现了错误的时候,在panic函数里面就会执行emergency_restart直接重启到normal kernle。

触发panic的方法

在一般情况下我们向触发panic的时候有一个简单的方法:那就是通过下面的命令:

echo c > /proc/sysrq-trigger

这个命令往sysrq-trigger中写入一个c。那么为什么为这个proc节点写入c就会导致宕机呢?
在sysrq-trigger中,当我们往里面echo c以后,这个节点会首先判断你输入的字符是什么,然后判断这个字符是什么,如果这个字符是c的话,那么就会执行panic的一个处理器(handler),在这个处理器中就会调用panic()函数。(这下知道了为啥这个可以触发宕机了吧。。)

/proc/kcore 与 /proc/vmcore

/proc/kcore 与 /proc/vmcore都是系统内存的镜像。那么他们都啥区别呢?
其中,/proc/kcore是normal kernel可见的,在crash kernel中不存在;在crash kernel中只有/proc/vmcore存在。
在系统启动的时候,会判断commandline中有没有参数 elfcorehdr=。在启动阶段,都会调用函数__init_vmcore函数,但是在这个函数里面会判断这次启动的内核是不是crash kernel,判断的方法及时通过判断elfcorehdr是否存在,以及这个elfcorehdr在不在一个合法的范围里面。如果通过了检查,这个时候就会调用proc_create创建/proc/vmcore这个节点,否则就不创建了。

vmcore的转储

在进入了crash kernel以后,就会开始使用makedumpfile对vmcore进行裁剪压缩。
在makedumpfile中,有lzo,snappy,zlib这三种的压缩方式,按照配置,对/proc/vmcore进行裁剪和压缩,过程会写到一个叫做vmcore-incomplete的文件中。
当完成了所有的操作了以后,就会调用命令:

mv vmcore-incomplete vmcore

然后调用reboot 重启到normal kernel

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐