赞
踩
生产内核(production kernel):产品或者线上服务器当前运行的内核。
捕获内核(capture kernel):系统崩溃时,使用kexec启动的内核,该内核用于捕获生产内核当前内存中的运行状态和数据信息。
Kdump是系统崩溃的时候,用来转储运行内存的一个工具。系统一旦崩溃,生产内核就没法正常工作,这时Kdump启动捕获内核,将此时内存中的所有运行状态和数据信息收集到一个dump core文件中,以便之后分析崩溃原因。一旦内存信息收集完成,系统将自动重启。
Kdump的核心实现基于Kexec(Kernel execution),kexec类似于Linux的exec系统调用。
Kexec可以快速启动一个新的内核(捕获内核),它会跳过BIOS或者Bootloader等引导程序的初始化阶段,这个特性可以让系统崩溃时快速切换到捕获内核,这样生产内核的内存就得到保留,Kdump的工作流程如下图所示:
捕获内核启动后,会像一般内核一样,去运行为它创建的ramdisk上的init程序。而各种转储机制都可以事先在init中实现。
为了在生产内核崩溃时能顺利启动捕获内核,捕获内核以及它的ramdisk是事先放到生产内核的内存中的(保留内存)。
生产内核的内存是通过/proc/vmcore这个文件交给捕获内核的,为了生成它,用户工具在生产内核中分析出内存的使用和分布等情况,然后把这些信息综合起来生成一个ELF头文件保存起来。捕获内核被引导时会被同时传递这个ELF文件头的地址,通过分析它,捕获内核就可以生成出/proc/vmcore。有了/proc/vmcore这个文件,捕获内核的ramdisk中的脚本就可以通过通常的文件读写和网络来实现各种策略了。
资料直通车:Linux内核源码技术学习路线+视频教程内核源码
Crash是一个用于分析内核转储文件的工具,和Kdump配套使用。Kdump会在内存中保留一块区域,这个区域用于存放捕获内核,生产内核运行过程中崩溃时,Kdump通过Kexec机制自动启动捕获内核,对生产内核的完整信息(CPU寄存器、栈帧数据等)进行保存,生产内核重启后,使用Crash工具来分析这个转储的文件。
使用对象:Linux物理机或者虚拟机;
使用场景:主要用于分析Linux系统崩溃问题;注意,在系统无法热启动的情况下,Kdump是不适用的,如硬件的异常导致CPU宕机,也就是只能通过重新关闭开启电源才能启动的情况。
本实验所使用的环境为VirtualBox+Ubuntu18.04。
Ubuntu配置的内核已经使能Kdump的支持,仅需要安装linux-crashdump包即可,运行命令如下:
sudo apt install linux-crashdump
该软件包含crash,kdump-tools,grub等相关依赖,安装中选择默认启动,如下图所示。
安装过程中会修改kernel cmdline已预留kdump转储转储内核内存空间,可以通过修改/etc/default/grub.d/kdump-tools.cfg文件修改保留内存的大小,默认为192M,如下图所示:
配置完成后更新grub(sudo update-grub),重启操作系统(reboot)。
使用kdump-config show命令查看kdump相关配置,如下图所示。
使用如下命令简单快速测试:
echo c > /proc/sysrq-trigger
如果Kdump配置正确,上述命令会让系统快速重启并且启动捕获内核进行转储,转储完成后会自动切换为生产内核,在进入生产内核的操作系统后,查看/var/crash目录中是否有根据年月日时分命名的文件夹,如下所示。
进入时间对应的目录,目录包含dmesg文件和dump文件,文件后缀为内核崩溃的时间,其中dmesg是生产内核发生崩溃时生成的内核日志信息,dump时捕获内核转储的文件,如下图所示。
打开Crash工具进行分析,Crash工具的使用方式如下:
crash [dump] [vmlinux]
Crash需要指定两个文件:
dump:转储的内核文件,通常在/var/crash目录下;
vmlinux:带调试内核符号信息的内核映像。
注意,Ubuntu系统默认不包含vmlinux文件,笔者已经对Ubuntu系统的内核进行更换,更换过程中生成带调试符号的vmlinux文件,具体步骤可以关注《话说Linux》订阅号,查看文章《Linux内核更换》。
crash启动dump文件界面如下。
9.1 help命令
help命令用于在线查看crash命令的帮助,在crash命令行中输入help命令可以查看crash支持的所有子命令。
help命令不仅可以查看crash支持的命令,还可以查看某个子命令的帮助说明,如查看bt命令的帮助说明。
9.2 bt命令
bt命令查看一个进程的内核栈的函数调用关系,包括所有异常栈的信息,常用参数如下。
上图可以看到,bt命令将系统崩溃瞬间正在运行的进程内核栈信息全部显示出来。当前进程的id是4265,task_struct数据结构的地址是0xffff8d026b198000,当前进程运行在CPU1上,当前进程的运行命令是bash。后面的栈帧列出了该进程在内核态的调用关系,执行顺序是自下而上。
9.3 mod命令
mod命令不仅可以用来显示当前系统加载的内核模块信息,还可以用来加载某个内核模块的符号信息和调试信息等,常用参数如下。
9.4 dis命令
dis命令用来输出反汇编结果,常用参数如下。
如输出sysrq_handle_crash()接口的反汇编结果。
以下是查看sysrq_handle_crash()接口源码的信息。
9.5 rd命令
rd命令用来读取内存地址中的值,常用参数如下。
以下命令用于读0xffff8d026b198000内存中的值,并连续输出16个内存地址中的值。
9.6 struct命令
struct命令用于显示内核中数据结构的定义或者具体的值,常用的参数如下。
以下命令用于显示task_struct数据结构的定义。
以下命令用于显示task_struct数据结构中每个成员的偏移量。
此外,struct命令后面还可以指定一个地址,用来按照数据结构的格式显示每个成员的值,例如已知task_struct数据结构的地址为0xffff8d026b198000,因此可以通过struct命令查看该数据结构中每个成员的值。
9.7 irq命令
irq命令用于显示中断的相关信息,常用参数如下。
9.8 task命令
task命令用于显示进程的task_struct数据结构和thread_info数据结构的内容。以下命令用于显示task_struct数据结构信息,其中-x表示以十六进制显示。
9.9 vm命令
vm命令用于显示进程地址空间的相关信息,常用参数如下。
以下命令用于显示当前进程的虚拟地址空间信息。
9.10 kmem命令
kmem命令用来显示系统内存信息,常用参数如下。
9.11 sym命令
sym命令用于解析内核符号信息,常用选项如下所示。
以下代码用于查看oops模块的所有符号信息。
9.12 list命令
list命令用来遍历链表,并且可以输出链表成员的值,常用的参数如下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。