当前位置:网站首页 > 技术博客 > 正文

kernelapcpendingduringnext



本文主要介绍kdump服务和crash的使用,并结合一个简单的实例演示如何分析内核崩溃的原因。本文基于Linux kernel 4.19, 体系结构为aarch64。

  1. 克转储

kdump 是一种基于 kexec 的内核崩溃转储机制,用来捕获内核 crash(内核崩溃)的时候产生的 crash dump。当内核产生错误时,kdump会将内存导出为vmcore保存到磁盘。

  1. kdump流程

当系统崩溃时,kdump 使用 kexec 启动到第二个内核。第二个内核通常叫做捕获内核,以很小内存启动以捕获转储镜像。第一个内核启动时会保留一段内存给kdump用。

  1. kdump的配置
  • 系统启动时为crashkernel保留内存

可以在内核命令行中加入如下参数:crashkernel=size[@offset]。保留内存是否预留成功,可以通过cat /proc/meminfo查看。。

cat /proc/meminfo |格雷普崩溃

  • 安装kexec-toools

yum install kexec-tools

kexec-tool推荐使用rpm方式安装,使用时需要和内核版本配套。

  • 启动kdump服务

systemctl start kdump.service // 启动kdump服务

service kdump status // 查看kdump状态

  • testkdump是否可以正常转储

echo c > /proc/sysrq-trigger

如果没有问题,系统会自动重启,重启后可以看到在/var/crash/目录下生成了coredump文件。

我们经常会使用qemu去启动虚拟机。qemu启动的内核发生错误也可以用kdump生成vmcore文件。

  1. 首先先将qemu的panic重启关闭,防止coredump的时候发生了重启

echo 0 > /proc/sys/kernel/panic

  1. 触发内核崩溃

echo c > /proc/sysrq-trigger

  1. kernel panic后,使得qemu进入monitor模式

ctrl + A, ---> c, qemu进入monitor模式

  1. 进入monitor模式后,进行coredump

dump-guest-memory -z xxx-vmcore

如下图所示,成功在qemu 的kernel panic后,获得了coredump文件。

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

在内核奔溃后,如果部署了kdump, 会在/var/crash目录中找到vmcore转储文件,vmcore文件可以配合crash工具进行分析。

crash的版本要和内核的版本保持一致, 比如上面成功dump了qemu arm64的coredump文件,就需要配套的arm64的crash工具进行分析,否则会报兼容性错误。

编译 ARM64 崩溃工具:

下载:https://github.com/crash-utility/crash/releases

编译安装:

$ tar -xf 崩溃-7.2.8.tar.gz

$ CD 崩溃-7.2.8/

$ 使目标=arm64

安装完成后,使用crash工具分析vmcore文件, vmlinux在编译内核时会在根目录下生成。

崩溃 VMcore VMLinux

crash常用命令

  • bt: 查看函数调用栈
 
  • log: 查看内核dmesg日志
 
  • struct: 查看数据结构
 

struct -o [struct] : 显示结构体中成员的偏移

struct [struct] [address] : 显示对应地址结构体的值

[结构][地址] :简化形式显示对应地址结构体的值

[结构][地址] -xo: 打印结构体定义和大小

[struct].member[address]: 显示某个成员的值

  • rd: 读取内存内容
 

rd [addr] [len]: 查看指定地址,长度为len的内存

rd -S [addr][len]: 尝试将地址转换为对应的符号

rd [addr] -e [addr] : 查看指定内存区域内容

  • dis: 进行返汇编,查看对应地址的代码逻辑
 
 
  • ps: 查看线程状态
 

ps -p [pid]: 显示进程父子关系

ps -t [pid]: 显示进程运行时间

  • kmem: 查看内核内存使用情况
 

kmem -i: 查看内存整体使用情况

kmem -s: 查看slab使用情况

kmem [addr]: 搜索地址所属的内存结构

  • 更多其它命令通过help查看

内核访问空指针产生panic。

  1. 驱动制作

编写一个驱动,构造一个内核模块访问空指针的异常,演示如何使用crash分析内核奔溃的原因。

 
 

将编好的驱动打包进根文件系统, 启动后插入内核模块。

  1. panic 分析 

内核的call trace如上图所示, 将对应的文件反汇编,找到问题出现对应的代码。

aarch64-linux-gnu-objdump -S panic-kernel.o > test.txt

截取部分反汇编如下:

 

从汇编代码可以看出, panic_foo函数的参数(x0)最终保存在x19寄存器。我们现在想要知道出现问题时,代码走的是哪一个分支。

配合crash进行分析,先导入模块符号表:

 

使用crash 查看出问题时结构体的值,确认函数走的是哪个分支。函数的参数是x19:

 

从打印的之来看,head成员的值为10, 可以确定代码走的是哪一个分支。

再结合之前的反汇编代码, 出错的位置在pc: panic_foo +0x54。pc保存的是栈顶指针,lr保存的是函数返回的地址(x30)

 

偏移54的位置是把w0的值保存到x21, 而x21的地址是0。w0的值是mov w0, 0xffff直接赋值得来的。所以这里是将0xffff直接写到0地址导致的问题。

综上如上信息,结合实际的代码,最终找到问题的原因。

 

版权声明


相关文章:

  • 应用层协议要定义哪些内容2025-05-02 14:01:00
  • 跳表数据结构与算法2025-05-02 14:01:00
  • string类的常用方法应用编程2025-05-02 14:01:00
  • 召回率精确率 准确率2025-05-02 14:01:00
  • offset函数的作用2025-05-02 14:01:00
  • c写log日志2025-05-02 14:01:00
  • 特征提取技术2025-05-02 14:01:00
  • maven中央仓库下载2025-05-02 14:01:00
  • html制作框架代码2025-05-02 14:01:00
  • 线程间通信机制2025-05-02 14:01:00