1. kdump
kdump 是一种先进的基于 kexec 的内核崩溃转储机制,用来捕获kernel crash(内核崩溃)的时候产生的crash dump。当内核产生错误时,kdump会将内存导出为vmcore保存到磁盘。
2. kdump流程
当系统崩溃时,kdump 使用 kexec 启动到第二个内核。第二个内核通常叫做捕获内核,以很小内存启动以捕获转储镜像。第一个内核启动时会保留一段内存给kdump用。

3. kdump的配置
(1) 系统启动时为crashkernel保留内存
可以在kernel command line中加入如下参数:crashkernel=size[@offset]
保留内存是否预留成功,可以通过cat /proc/meminfo查看。
(2) 安装kexec-toools
kexec-tool推荐使用rpm方式安装,使用时需要和内核版本配套。
(3) 启动kdump服务
(4) 测试kdump是否可以正常dump
如果没有问题,系统会自动重启,重启后可以看到在/var/crash/目录下生成了coredump文件
(2) 触发kernel panic
(3) kernel panic后,使得qemu进入monitor模式
(4) 进入monitor模式后,进行coredump
如下图所示,成功在qemu 的kernel panic后,获得了coredump文件。

在内核奔溃后,如果部署了kdump, 会在/var/crash目录中找到vmcore转储文件,vmcore文件可以配合crash工具进行分析。
crash的版本要和内核的版本保持一致, 比如上面成功dump了qemu arm64的coredump文件,就需要配套的arm64的crash工具进行分析,否则会报兼容性错误。
编译arm64 crash工具:
安装完成后,使用crash工具分析vmcore文件, vmlinux在编译内核时会在根目录下生成。

crash常用命令
- bt: 查看函数调用栈
- log: 查看内核dmesg日志
- struct: 查看数据结构
struct -o [struct] : 显示结构体中成员的偏移
struct [struct] [address] : 显示对应地址结构体的值
[struct] [address] : 简化形式显示对应地址结构体的值
[struct] [address] -xo: 打印结构体定义和大小
[struct].member[address]: 显示某个成员的值
- rd: 读取内存内容
rd [addr] [len]: 查看指定地址,长度为len的内存
rd -S [addr][len]: 尝试将地址转换为对应的符号
rd [addr] -e [addr] : 查看指定内存区域内容
- dis: 进行返汇编,查看对应地址的代码逻辑
- ps: 查看线程状态
- kmem: 查看内核内存使用情况
kmem -i: 查看内存整体使用情况
kmem -s: 查看slab使用情况
kmem [addr]: 搜索地址所属的内存结构
- 更多其它命令通过help查看
内核访问空指针产生panic
(1) 驱动制作
编写一个驱动,构造一个内核模块访问空指针的异常,演示如何使用crash分析内核奔溃的原因。
驱动代码如下:
panic-kernel.c
Makefile
将编好的驱动打包进根文件系统, 启动后插入内核模块

内核panic, 手动生成vmcore文件。
截取部分反汇编如下:
从汇编代码可以看出, panic_foo函数的参数(x0)最终保存在x19寄存器,。
我们现在想要知道出现问题时,代码走的是哪一个分支。
配合crash进行分析
先导入模块符号表:
从打印的之来看,head成员的值为10, 可以确定代码走的是哪一个分支。
偏移54的位置是把w0的值保存到x21, 而x21的地址是0
w0的值是mov w0, 0xffff直接赋值得来的。 所以这里是将0xffff直接写到0地址导致的问题。
综上如上信息,结合实际的代码,最终找到问题的原因。
Kdump 原理探秘
深入学习kdump原理
系统崩溃 - crash工具介绍
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/15188.html