最近想运用qemu建立一个能调试kdump与crash的环境,用来学习运用crash东西处理一些内核panic、死机、重启安稳性问题,也能更好的学习内核,于是找了一些材料,发现runninglinuxkernel_5.0介绍的比较详细,所以想依照这个文档先建立个环境进行学习。(如有侵权,可删除)

kdump是一个内核转储东西,其核心是根据Kexec(kernel execution),能够快速启动一个新的内核,它会跳过BIOS或许bootloader等引导程序的初始化阶段,这样在体系溃散时快速切换到一个备份的内核,这样榜首个内核的内存就得到保存。在第二个内核中能够对榜首个内核产生的溃散数据(寄存器、栈、堆等内存数据)进行dump,写到本地磁盘,然后经过crash东西进行离线剖析。

crash是redhat的工程师开发的,首要用来离线剖析linux内核转存文件,它整合了gdb东西,功用非常强壮。能够检查堆栈,dmesg日志,内核数据结构,反汇编等等,是剖析linux内核panic、死机、重启等疑难问题的利器。

1、环境建立

1.1 环境版别

  1. 主机硬件渠道:Intel x86_64处理器笔记本。
  2. 主机操作体系:Ubuntu Linux 20.04
  3. GCC版别:9 (aarch64-linux-gnu-gcc-9)

《奔跑吧Linux内核》源码

1.2 建立qemu虚拟机环境

1.2.1 vmware环境建立

网上有很多相关材料参阅

1.2.2 装置软件包

在Ubuntu Linux 20.04能够经过如下指令来装置需求的软件包:

$ sudo apt update -y
$ sudo apt install net-tools libncurses5-dev libssl-dev build-essential openssl qemu-system-arm libncurses5-dev gcc-aarch64-linux-gnu git bison flex bc vim universal-ctags cscope cmake python3-dev gdb-multiarch openjdk-13-jre trace-cmd kernelshark bpfcc-tools cppcheck docker docker.io
1.2.3 下载runninglinuxkernel源码
mkdir runninglinuxkernel
cd runninglinuxkernel
git clone https://github.com/figozhang/runninglinuxkernel_5.0.git
1.2.4 编译linux内核
$ cd runninglinuxkernel_5.0
$ ./run_debian_arm64.sh build_kernel
1.2.5 编译根文件体系
$ cd runninglinuxkernel_5.0
$ sudo ./run_debian_arm64.sh build_rootfs
1.2.6 运转qemu环境
$ cd runninglinuxkernel_5.0
$ ./run_debian_arm64.sh run

执行时遇到virtio-9p-pci is not a valid device model name问题(virtio-9p-pci是一个用来在ubuntu与qemu虚拟机之间进行文件同享的模块,能够直接将ubuntu上的文件直接拷贝到qemu,而不用向之前一样还需求从头编译根文件体系),原因是我运用的qemu版别是 5.1.0,经过qemu-system-aarch64 -device help检查的确是没有virtio-9p-pci这个device,参阅这个qemu virtio-9p-pci is not a valid device model name的处理办法,需求从头装置qemu。

$ wget https://download.qemu.org/qemu-5.1.0.tar.xz
$ tar xvJf qemu-5.1.0.tar.xz 
$ cd qemu-5.1.0
$ qemu-system-aarch64 --version
QEMU emulator version 5.1.0
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers
//加上--enable-virtfs使得qemu能支撑virtio-9p-pci,留意需求 libcap 和 libattr 等依靠库
//可运用apt-get build-dep qemu去装置一切的依靠库
$ apt-get build-dep qemu
$ ./configure --target-list=x86_64-softmmu,x86_64-linux-user,arm-softmmu,arm-linux-user,aarch64-softmmu,aarch64-linux-user --enable-kvm --enable-virtfs
$ make 
$ sudo make install

再测验运转qemu环境:

$ cd runninglinuxkernel_5.0
$ ./run_debian_arm64.sh run

基于qemu的kdump与crash环境搭建与实例解析

1.3 kdump环境

在qemu虚拟机环境中,运用systemctl status kdump-tools指令来检查kdump服务是否正常作业。如下图,当显现的状况为active表明kdump启动成功。

基于qemu的kdump与crash环境搭建与实例解析

2、制作panic并获取转储文件

运用echo c > /proc/sysrq-trigger手动制作一个panic,然后触发重启,进入第二内核:

基于qemu的kdump与crash环境搭建与实例解析

进入第二内核后,会调用makedumpfile进行内核信息转储(或许需求几分钟时刻进行加载),转储完成后,自动重启再进去榜首内核:

基于qemu的kdump与crash环境搭建与实例解析

3、运用crash剖析转储文件

在ubuntu将带调试符号信息的vmlinux文件拷贝到同享文件夹kmodules,在qemu即可拜访这个文件:

基于qemu的kdump与crash环境搭建与实例解析

接下来在qemu中进入/var/crash目录,转储文件的目录是以日期来命名,然后运用crash东西来加载内核转储文件进行剖析(或许需求几分钟时刻进行加载):

基于qemu的kdump与crash环境搭建与实例解析

可输入指令来进行各种剖析:

  1. help:用于检查crash指令的协助

基于qemu的kdump与crash环境搭建与实例解析

一个比较有用的技巧是运用 help 子指令 检查某个子指令的协助说明:

基于qemu的kdump与crash环境搭建与实例解析

  1. bt:输出进程的内核栈函数调用关系
  • -t:显现栈中一切文本符号
  • -f:显现每一栈帧里的数据
  • -l:显现文件名和行号
  • pid:显现指定PID进程的内核栈的函数调用信息

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

  1. dis:用来输出反汇编成果

基于qemu的kdump与crash环境搭建与实例解析

  1. rd:读取内存地址中的值

基于qemu的kdump与crash环境搭建与实例解析

  1. struct:显现内核中数据结构的界说或许详细的值

struct xxx -o来显现每个成员的偏移量

基于qemu的kdump与crash环境搭建与实例解析

另外,struct xxx -x addr,能够指定一个地址,用来依照struct的格局以16进制显现每个成员的值,这个在实战中十分的有用。

基于qemu的kdump与crash环境搭建与实例解析

  1. p:输出内核变量、表达式或许符号的值

p jiffies:输出jiffies的值

基于qemu的kdump与crash环境搭建与实例解析

p init_mm:输出进程0的mm数据结构的值

基于qemu的kdump与crash环境搭建与实例解析

p irq_stat:如果一个变量时Per-CPU类型,那么会输出一切Per-CPU变量的地址,p irq_stat:0用来输出某个CPU上内核符号的值

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

  1. irq:显现中止相关信息
  • index:显现某个指定irq的信息
  • -b:显现中止下半部信息
  • -s:显现体系中止信息

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

  1. task:用来显现进程task_struct数据结构和thread_info数据结构的内容,其中-x表明依照16进制显现。

基于qemu的kdump与crash环境搭建与实例解析

task -R on_cpu,on_rq,comm 709:检查进程中task_struct中的成员

基于qemu的kdump与crash环境搭建与实例解析

  1. vm:显现进程的地址空间相关信息
  • -p:显现虚拟地址和物理地址
  • -m:显现mm_struct数据结构
  • -R:搜索特定字符串或许数值
  • -v:显现该进程中一切vm_area_struct数据结构的值
  • -f num:显现数字在vm_flags中对应的位

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

  1. kmem:显现体系的内存信息
  • -i:显现体系内存的运用状况
  • -v:显现体系vmalloc的运用状况
  • -V:显现体系vm_stat状况
  • -s:显现slab运用状况
  • -p:显现每个页面的运用状况
  • -g:显现page数据结构里flags的标志位

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

基于qemu的kdump与crash环境搭建与实例解析

  1. list遍历链表,并且能够输出链表成员的值
  • -h:指定链表头(list_head)的地址
  • -s:用来输出链表成员的值
  1. 计算内存的运用状况

计算一切用户进程一共占用了多少内存:

ps -u | awk '{ total += $8 } END { printf "Total RSS of user-mode: %.02f GB\n", total/220 }'

基于qemu的kdump与crash环境搭建与实例解析

计算哪些进程占用的内存最多:

ps -u | awk '{ m[$9] += $8 } END { for (item in m) { printf "%20s %10s KB\n", item, m[item] } }' | sort -k 2 -r -n

基于qemu的kdump与crash环境搭建与实例解析

  1. 检查进程状况

ps | grep UN:检查体系有哪些进程处于不可中止状况

基于qemu的kdump与crash环境搭建与实例解析

ps | grep RU:检查体系有哪些进程处于运转状况

基于qemu的kdump与crash环境搭建与实例解析

ps | grep -c RU:检查体系处于运转状况的进程个数

基于qemu的kdump与crash环境搭建与实例解析

  1. foreach:遍历体系中一切进程并且做一些计算方面的作业

foreach RU bt:遍历体系一切处于运转状况进程的堆栈

基于qemu的kdump与crash环境搭建与实例解析

  1. 检查CPU和进程时刻戳

runq -t:检查每个CPU上最近运转的时刻戳与task

基于qemu的kdump与crash环境搭建与实例解析

ps -l:检查每个进程最近运转的时刻戳

基于qemu的kdump与crash环境搭建与实例解析

  1. 检查dmesg log

基于qemu的kdump与crash环境搭建与实例解析