技术交流

好好学习,天天向上。

0%

Crash调试内核崩溃

介绍

Kdump是一种内核崩溃转储机制,其依靠底层的kexec工作。kexec是一种内核套内核的系统启动机制,它会让系统启用两层内核。用户看到的内核在最里层,当用户内核崩溃的时候,处于外层的内核接管控制权限。此时,外层内核会执行一些数据保存工作。外层内核驻留在内存中,且这片内存对内层内核不可见。

安装

1
2
yum install kexec-tools crash -y
debuginfo-install kernel

配置

1
yum install system-config-kdump # 安装图形配置工具

测试

1
2
3
4
5
systemctl status kdump // 测试服务是否正常
systemctl is-active kdump

echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger

若服务没启动,极有可能是kdump内核占用太大,预留的内存容量不够或者无法预留太大的内存。若在两个echo没有crash生成,极有可能是预留内存太小,导致dump内核OOM了。针对这些问题,解决办法是要么减少kdump内核大小,要么增大预留空间。

  • 减少内存条,内存越大需要预留的内存就越大,有时候内核无法找到连续的大块物理内存

  • 修改crashkernel内核参数,手动调整预留内存大小和偏移(难度较高,不推荐)

  • 压缩dump内核大小,也就是/boot下的initramfs-xxx.img。另外发现arm和x86的initramfs格式不同,可以通过file命令判断。下面是针对gzip格式的解包和打包方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    cd /boot
    cp initramfs-$(uname -r).$(uname -m)kdump.img initramfs-$(uname -r).$(uname -m)kdump.img.bak
    mv initramfs-$(uname -r).$(uname -m)kdump.img initramfs-$(uname -r).$(uname -m)kdump.img.gz
    gunzip initramfs-$(uname -r).$(uname -m)kdump.img.gz
    mkdir temp
    cd temp
    cpio -i -F ../initramfs-$(uname -r).$(uname -m)kdump.img
    rm -rf lib/modules/$(uname -r).$(uname -m)/extra
    find . | cpio -ov -H newc |gzip > ../initramfs-$(uname -r).$(uname -m)kdump.img
    cd ..
    rm temp -rf
  • 通过system-config-kdump,反勾选那些不必要的dump项

    调试

1
crash /usr/lib/debug/lib/modules/<kernel>/vmlinux \ /var/crash/<timestamp>/vmcore

常用命令

1
2
3
4
5
6
7
8
9
10
11
# Crash 加载模块
mod -s <name> /path/to/name.ko

# 查看地址对应的代码位置
sym 0000ffffb6daa6f4

# 打印崩溃的调用栈
bt

# 反汇编某个符号
dis xxxx_symbol_name

常用解释

内核崩溃时会有类似下面这样的打印,这个打印中,0x23的含义是在该符号名称的0x23个byte的偏移处,0x50的含义是这个符号总大小是0x50个byte。

1
xxxx_symbol_name+0x23/0x50 # 通过sym xxxx_symbol_name得到的值再加上0x23就是打印处的地址,可以对该值再sym就可以得到代码行