内核崩溃kdump(sysdump)和crash分析
系统一旦崩溃,内核就没法正常工作了,这个时候需要触发一种转存储机制(kernel中的kdump, unisoc的sysdump)。转存机制提供一个用于捕获当前运行现场的内核,该内核会将此时内存中的所有运行状态和数据信息收集到一个dump core文件中以便之后分析崩溃原因。
在系统发生诸如Kernel crash等异常时,在Kernel中完成flush cache等处理后,重启进入dump内核收集和保存现场数据。
crash, 是某个特定时刻(如kernel panic)的系统RAM的快照,需要转存的现场数据。
约束条件:
kdump 、sysdump 通常用于假死机(unresposive)和panic,也就是没有响应的情况下。硬件问题导致的死机,无能为力。
1.kdump
kdump是kernel原生的一个系统奔溃时的现场转存工具。kdump是RHEL5之后才支持的,2006被主线接收为内核的一部分。它的原理简单来说是在内存中保留一块区域,这块区域用来存放capture kernel,当production kernel发生crash的时候,通过kexec把保留区域的capure kernel给运行起来,再由捕获内核负责把产品内核的完整信息,包括CPU寄存器、堆栈数据等转储到指定位置的文件中。
(1) kdump运行原理介绍
kdump实现了"双内核"布局,Kdump 在内核在内核panic后,立即调用kexec 引导到转储捕获内核(capture kernel),使用 kexec 引导 “覆盖” 当前运行的内核。
该“转储捕获内核”的内存区域由主内核的bootargs参数 crashkernel 或dts指定。“转储捕获内核”可以是专门build的单独 Linux 内核image,也可以在支持可重定位内核的系统架构上重用主内核映像。
kexec(kernel execution,类似于 Unix 或 Linux 的系统调用 exec)是 Linux 内核的一种机制,其允许从当前运行的内核启动新内核。kexec 会跳过由系统固件(BIOS或UEFI、bootloader)执行的引导加载程序阶段和硬件初始化阶段,直接将新内核加载到主内存并立即开始执行。这避免了完全重新启动的漫长时间,并且可以通过最小化停机时间来满足系统高可用性要求。
注意: 不经过bootloader或bios阶段,直接从主kernel启动到“转储捕获内核”进行。

(2) dump触发方式
1.手动触发
- 通过sysrq触发
echo c /proc/sysrq-trigger
- 通过IPMI触发不可屏蔽中断
ipomitool power diag
- 通过virsh触发不可屏蔽中断
virsh inject-nmi MyGuestName
- Beware of
kernel.unkonow_nmi_panic=1
2.自动触发
- watchdong(看门狗)
cmdline中:nmi_watchdog=1
- softlockup(软锁)
sysctl kernel.softlockup_panic=1
- 内存越界
sysctl vm.panic_on_oom=1

2.sysdump
SysDump即Dump system memory,是sysdump的一种转存储机制,是将发生异常时的内存信息、寄存器信息等有效信息转存为文件,以便于借助分析工具分析问题现场。
在系统发生诸如Kernel crash等异常时,在Kernel中完成flush cache等处理后,重启进入Uboot(或LK等bootloader阶段)中完成所有数据的保存,保存过程会有相应屏幕提示,完成后根据屏幕提示重启手机,导出异常数据文件进行分析。
SysDump分为FullDump和MiniDump两个子功能,两个子功能是互不影响的。
- FullDump保存完整DDR信息,可以支持两种存储路径Dump2SD和Dump2PC。Dump2SD功能依赖于SD卡,即设备需支持插入SD卡。
- MiniDump保存少量信息到单独的SysDumpdb分区,然后再由native sevice 程序将分区保存的raw数据整理解析后放置到/sdcard/MiniDump路径下。
MiniDump功能仅Android系统的设备支持。
在资源允许的条件下,优先选择保存分析FullDump日志,因为其保存了完整的现场信息快照,更有利于深入分析问题。
(1) sysdump运行原理介绍

系统异常和组合键主动触发系统异常都会走到Kernel的处理流程,但长按7s(秒)的操作不会进入Kernel处理流程。
- MiniDump在Kernel阶段完成初始化和异常处理时的数据保存。
- Uboot中完成数据的存储操作,包括FullDump 和MiniDump。
(2) dump触发方式
硬件配置不同,SysDump触发方式也有所差异,具体如下。

3.转存文件的解析—crash工具
前面提到,当系统崩溃时,通过kdump或sysdump可以获得当时的内存转储文件vmcore,但是该如何分析vmcore呢?
crash是一个用于分析内核转储文件的工具,一般和kdump搭配使用,sysdump也可以使用该工具解析。
使用crash时,要求调试内核vmlinux在编译时带有-g选项,即带有调试信息。如果没有指定vmcore,则默认使用实时系统的内存来分析。
值得一提的是,crash也可以用来分析实时的系统内存,是一个很强大的调试工具。crash使用gdb作为内部引擎,语法类似于gdb,命令的使用说明可以用 help来查看。
(1) crash工具的依赖
使用crash需要安装crash工具包和内核调试信息包:
crash
kernel-debuginfo-common
kernel-debuginfo
对于在PC上调试arm平台的异常现场,使用专用的crash工具,不需要安装,直接运行。
工具获取路径:

工具说明:
crash_arm:用于32bit ARM 平台
crash_arm64:用于64bit ARM 平台
(2) crash工具的使用
使用crash来调试vmcore,至少需要两个参数:
- 未压缩的内核映像文件vmlinux。ubuntu默认位于/usr/lib/debug/lib/modules/$(uname -r)/vmlinux,由内核调试信息包提供。
- 内存转储文件vmcore,由kdump或sysdump转存的内核奔溃现场快照。
对于ARM平台来说,除上述参数之外,一般还需要指定如下参数:
- phys_offset: RAM的起始物理地址
- vabits_actual: 实际的虚拟地址空间大小(总线位宽)
- kimage_voffset: kernel image映射的物理地址偏移
以unisoc ARM64平台为例,crash执行命令:
./crash_arm64 -m vabits_actual=39 -m phys_offset=0x80000000 -m kimage_voffset=0xffffffbf90000000 ./vmlinux ./vmcore
(3) crash基本输出分析
crash基本输出:
~/crash$ ./crash_arm64_v8 -m vabits_actual=39 -m phys_offset=0x80000000 -m kimage_voffset=0xffffffbf90000000 ./vmlinux ./syscore
crash_arm64_v8 8.0.0++
Copyright (C) 2002-2021 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011, 2020-2021 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
Copyright (C) 2015, 2021 VMware, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.
NOTE: setting vabits_actual to: 39
NOTE: setting phys_offset to: 0x80000000
NOTE: setting kimage_voffset to: 0xffffffbf90000000
GNU gdb (GDB) 10.2
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=aarch64-elf-linux".
Type "show configuration" for configuration details.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
WARNING: cpu 0: cannot find NT_PRSTATUS note
KERNEL: ./vmlinux [TAINTED]
DUMPFILE: ./syscore
CPUS: 8 [OFFLINE: 7]
DATE: Wed Sep 14 16:38:14 CST 2022
UPTIME: 01:48:53
LOAD AVERAGE: 10.46, 10.99, 10.55
TASKS: 1564
NODENAME: localhost
RELEASE: 5.4.190-android12-9-02871-g77dc16611297
VERSION: #1 SMP PREEMPT Wed Sep 14 10:55:40 CST 2022
MACHINE: aarch64 (unknown Mhz)
MEMORY: 3 GB
PANIC: "Kernel panic - not syncing: sysrq triggered crash"
PID: -1
COMMAND: "bash"
TASK: ffffff801e604b00 (1 of 32) [THREAD_INFO: ffffff801e604b00]
CPU: -1
STATE: TASK_INTERRUPTIBLE|TASK_UNINTERRUPTIBLE|TASK_STOPPED|TASK_TRACED|EXIT_DEAD|TASK_DEAD|EXIT_ZOMBIE|TASK_WAKING|TASK_WAKEKILL|TASK_NOLOAD|TASK_NEW
crash_arm64_v8>
这些基本输出信息简单明了,可由sys命令触发。
其中各项参数的意义为:
- KERNEL表示调试用内核的位置和版本信息
- DUMPFILE: 表示所分析的内存转储镜像
- CPUS: 表示本机的 CPU 数目
- DATE: 表示内核崩溃发生的时间
- UPTIME: 表示内核已正常运行的时间
- LOAD AVERAGE: 表示内核崩溃时系统的负载
- TASKS: 表示内核崩溃时系统运行的任务数
- NODENAME: 表示内核崩溃的机器的主机名
- RELEASE: 表示内核的发布版本
- VERSION: 表示内核的其他版本信息
- MACHINE: 表示 CPU 的架构和主频信息
- MEMORY: 表示发生内核崩溃的系统的内存大小
- PANIC: 表示内核崩溃的类型
- PID: 表示导致内核崩溃的进程号;
- COMMAND: 表示导致内核崩溃的进程名称
- TASK: 表示导致内核崩溃的进程访问的内存地址;
- CPU: 表示导致内核崩溃的进程占用的 CPU 数目;
- STATE: 表示导致内核崩溃的进程的运行状态。
需要重点关注的是 13. PANIC,它告诉我们内核奔溃的原因。一般有如下类型:
- SysRq。即通过系统请求造成的内核崩溃,如上面测试用的命令。
- Oops。表示内核发生了不可预期的或不正确的行为,这时会杀死相应的进程,内核可能恢复正常,也可能处于一种不确定的状态,并进而导致内核的 Panic。
- Panic。 内核崩溃,即发生了严重且不可修复的错误, 如发生了非法的地址访问, 强制加载或卸载内核模块,以及硬件错误等等。
以上信息可用于初步分析内核崩溃的原因,内核态有三种出错情况,分别是 bug, oops和 panic。 bug 属于轻微错误, oops 代表某一用户进程出现错误,需要杀死用户进程。这时如果用户进程占用了某些信号锁,这些信号锁将永远不会得到释放,这会导致系统潜在的不稳定性。 panic 是严重错误,代表整个系统崩溃。 深入的分析需要使用更多的命令进行追踪和查找。
(4) crash常用命令
查看某个命令的详细介绍:help xxx
crash_arm64_v8> help
* files mod sbitmapq union
alias foreach mount search vm
ascii fuser net set vtop
bpf gdb p sig waitq
bt help ps struct whatis
btop ipcs pte swap wr
dev irq ptob sym q
dis kmem ptov sys
eval list rd task
exit log repeat timer
extend mach runq tree
crash_arm64_v8 version: 8.0.0++ gdb version: 10.2
For help on any command above, enter "help <command>".
For help on input options, enter "help input".
For help on output options, enter "help output".
crash_arm64_v8> help xxx
1.bt命令:
打印函数调用栈,displays a task’s kernel-stack backtrace 。
- -t: 显示符号信息
- -f: 显示栈的所有数据
- -l: 显示文件名和行号
- pid: 可以显示指定pid进程的backtrace
crash_arm64_v8> ps |grep UN
161 2 4 ffffff80b62a9e00 UN 0.0 0 0 [sprd-rotation/6]
162 2 4 ffffff80b62abc00 UN 0.0 0 0 [sprd-rotation/7]
228 2 0 ffffff80b52be900 UN 0.0 0 0 [slog-0-0]
730 2 0 ffffff8088c58000 UN 0.0 0 0 [RX_THREAD]
731 2 0 ffffff8088c58f00 UN 0.0 0 0 [RX_NET_QUEUE]
732 2 6 ffffff8088c5cb00 UN 0.0 0 0 [SPRDWL_TX_THREA]
847 2 6 ffffff80795bbc00 UN 0.0

本文介绍了内核崩溃时的转存机制kdump和sysdump的工作原理,以及如何利用crash工具进行内存转储文件的分析。文章详细解释了kdump的运行机制、触发方式,并对比了sysdump的特点。此外,还提供了crash工具的基本使用方法和常见命令。
最低0.47元/天 解锁文章
300

被折叠的 条评论
为什么被折叠?



