centos7 kdump、crash调试内核

本文介绍了kdump和crash的原理及使用方法。kdump可在内核崩溃时创建crashdumps,导出内存映像(vmcore),供crash工具分析以调试和确定崩溃原因。crash工具支持分析vmcore文件或实时系统内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

Linux 应用层可以用gdb调试应用程序和出现段错误时产生的coredump文件,那么在内核层了,调试内核的工具是crash,使用方法和gdb类似,接下来我就在centos7 安装crash调试环境,并进行一些demo测试。

我当前的环境:
在这里插入图片描述

一、kdump

1.1 kdump定义

来自维基百科的定义:

kdump 是 Linux 内核的一项功能,可在kernel crash(内核崩溃)时创建 crash dumps。 触发时,kdump 会导出一个内存映像(也称为 vmcore),可以对其进行分析,以用于调试和确定崩溃原因。 主内存的转储映像,作为可执行和可链接格式 (ELF) 对象导出,可以在处理 kernel crash 期间直接通过 /proc/vmcore 访问,或者它可以自动保存到本地可访问的文件系统、原始设备或可通过网络访问的远程系统。

在内核崩溃的情况下,kdump 通过启动另一个 Linux 内核(称为 dump-capture kernel,)并使用它来导出和保存内存转储来保持系统一致性。 系统引导到一个干净可靠的环境,而不是依赖可能导致各种问题的已经崩溃的内核。kdump 使用 kexec 在内核崩溃后立即"warm"引导到dump-capture kernel,使用 kexec 的“引导”当前运行的内核的能力,同时避免执行引导加载程序和系统固件(BIOS 或 UEFI)。dump-capture kernel 可以是专门为此目的构建的独立Linux内核映像,也可以在支持可重定位内核的体系结构上重用主内核映像。

在引导并运行dump-capture kernel时,通过提前预留少量RAM来保留主内存(RAM)的内容,dump-capture kernel预加载到其中,因此在处理内核崩溃时不会覆盖主内核使用的任何 RAM,此保留的 RAM 量仅由 dump-capture kernel 使用,在正常系统操作期间不会使用该保留的 RAM。

对于x86架构 需要一小部分固定位置的 RAM 来引导内核,而不管它加载到哪里; 在这种情况下,kexec 创建该部分 RAM 的副本,以便dump-capture kernel也可以访问它。RAM 保留部分的大小和可选位置通过内核启动参数 crashkernel 指定,并且在主内核启动后使用 kexec 命令行程序( command-line utility )将dump-capture kernel image 及其关联的 initrd image 预加载到保留的那小部分内存。

除了作为 Linux 内核一部分的功能之外,其他用户空间实用程序支持 kdump 机制,包括上面提到的 kexec 实用程序。除了作为 kexec 用户空间实用程序套件的补丁提供的官方实用程序之外,一些 Linux 发行版 提供额外的实用程序来简化 kdump 操作的配置,包括自动保存内存转储文件的设置。 可以使用 GNU Debugger (gdb) 或使用 Red Hat 的专用crash utility 来分析创建的内存转储文件(memory dump files,即:vmcore)。

kdump 功能与 kexec 在内核版本 2.6.13 中合并到 Linux 内核主线中。

简单点来说就是:在主内核的保留一块内存区域,这块内存用来存放dump-capture kernel (我们暂且称它为捕获内核),当主内核发生crash(崩溃)的时候,通过kexec 运行保留在内存区域的 捕获内核 dump-capture kernel ,再由dump-capture kernel 负责把主内核发生故障时完整信息 - 包括CPU寄存器、堆栈数据等转储到指定位置的文件 vmcore(elf core 文件)中。

可见kdump 需要两个不同目的的内核,主内核(也叫生产内核)和捕获内核。主内核是捕获内核服务的对像。捕获内核会在生产内核崩溃时启动起来,与相应的 ramdisk 一起组建一个微环境,用以对生产内核下的内存进行收集和转存。

1.2 原理架构图

在这里插入图片描述

1.3 kdump配置

(1)kexec-tools
在centos7 中,kexec-tools都是已经默认安装的,我们可以用以下命令查看:

kexec -v

在这里插入图片描述
(2)安装 debuginfo-install
(如果调试的出现 :Missing separate debuginfos, use: debuginfo-install … 等错误,需用debuginfo-install安装各种调试包)

vim /etc/yum.repos.d/CentOS-Debuginfo.repo

将enabled参数由0改为1
在这里插入图片描述

yum install nss-softokn-debuginfo –nogpgcheck  yum-utils -y

然后就可以用 debuginfo-install 命令安装各种调试依赖了。

(3)kernel-debuginfo包
要调式内核故障时产生的vmcore文件,我们需要带有调试信息的内核,需要安装对应版本的kernel-debuginfo包。
如下所示:

 yum install -y kernel-debuginfo-$(uname -r)

kernel-debuginfo-common
kernel-debuginfo

在这里插入图片描述
(4)捕获内核
捕获内核是一个未压缩的ELF映像文件,查看捕获内核是否加载到内存中:

 cat /sys/kernel/kexec_crash_loaded

在这里插入图片描述
可见捕获内核已经加载到内存中了。

捕获内核占用内存情况查看:内核自动设置为auto(当然也可以自己修改)

 cat /proc/cmdline

在这里插入图片描述

系统auto 自动为捕获内核预留的内存查看:通过 /proc/iomem 中查看预留内存的物理分布:
在这里插入图片描述
通过dmesg和kdumpctl也可以查看:

dmesg | grep  "Reserving .* crashkernel"
kdumpctl showmem

在这里插入图片描述

(5)kdump配置
可以修改内核引导参数,为启动捕获内核预留指定内存:

vim /etc/default/grub

在这里插入图片描述
可以把 GRUB_CMDLINE_LINUX="crashkernel=auto 改为 GRUB_CMDLINE_LINUX="crashkernel=256M,这里我没有改。
修改/etc/default/grub文件后就要grub配置:

grub2-mkconfig -o /boot/grub2/grub.cfg
reboot

在这里插入图片描述
修改配置文件:

vim /etc/kdump.conf

在这里插入图片描述
自己根据实际情况修改。

二、crash

2.1 crash简介

上文说到 kdump 可在内核崩溃时创建 crash dumps,kdump 会导出一个内存映像( vmcore),我们可以对其进行分析,以用于调试和确定崩溃原因,分析的工具就是crash。

crash -:Analyze Linux crash dump data or a live system。可以看出crash既可以分析崩溃时产生的vmcore,又可以分析实时的系统内存。
在这里插入图片描述

crash要求调试内核vmlinux在编译时带有-g选项,即带有调试信息,在上面我们已经下载对应的安装包了。

yum install crash

在这里插入图片描述
按crash命令直接就可以调试 live system 了。
在这里插入图片描述
/usr/lib/debug/lib/modules/3.10.0-957.el7.x86_64/vmlinux 是未压缩的可执行的内核映像文件。
(1)crash 支持的命令
在这里插入图片描述

(2)dis命令
dis - disassemble
来举个例子说明dis的使用: dis address :starting hexadecimal text address.

查看符号sk_load_half_positive_offset的地址:

 cat /proc/kallsyms | grep "\<sk_load_half_positive_offset\>"

在这里插入图片描述

dis ffffffff91e8f541

在这里插入图片描述
然后我们再看看内核源码关于该函数的代码:
内核版本3.10.1 ,文件位置arch/x86/net/bpf_jit.S ,是一个汇编文件

//arch/x86/net/bpf_jit.S

sk_load_half_positive_offset:
	.globl	sk_load_half_positive_offset

	mov	%r9d,%eax
	sub	%esi,%eax		#	hlen - offset
	cmp	$1,%eax
	jle	bpf_slow_path_half
	movzwl	(SKBDATA,%rsi),%eax
	rol	$8,%ax			# ntohs()
	ret

可以看出我们通过crash dis反汇编出来的代码与源码一样。

2.2 crash调试 vmcore

我们手动触发一次 panic:

echo c > /proc/sysrq-trigger

在这里插入图片描述
触发后,系统直接重启。

由前面我们可以知道:当系统崩溃时,kdump 使用 kexec 启动到第二个内核,即捕获内核,以很小内存启动以捕获转储镜像。第一个内核保留了内存的一部分给第二内核启动用。由于 kdump 利用 kexec 启动捕获内核,绕过了 BIOS,所以第一个内核的内存得以保留。

内存转储文件vmcore,默认位于/var/crash/%HOST-%DATE/vmcore,由kdump生成。
在这里插入图片描述
在这个目录下我们看到了两个文件vmcore 和 vmcore-demsg.txt
现在我们用crash调试这个vmcore:

crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux   vmcore

在这里插入图片描述
其中一些参数解释:
KERNEL:系统崩溃时运行的 kernel 文件
DUMPFILE:内核转储文件
TASKS:系统崩溃时内存中的任务数
PANIC:崩溃类型,常见的崩溃类型包括:
(1)SysRq(System Request):通过组合键导致的系统崩溃,通常是测试使用。通过 echo c > /proc/sysrq-trigger,就可以触发系统崩溃。
c :Crashes the system without first unmounting file systems or syncing disks attached to the system.

(2)oops:可以看成是内核级的 Segmentation Fault,比如内存访问越界或者非法指令(最常见的就是使用空指针)。应用程序如果进行了非法内存访问或执行了非法指令,会得到 Segfault 信号,一般行为是 coredump,应用程序也可以自己截获 Segfault 信号,自行处理。如果内核自己犯了这样的错误,则会弹出 oops 信息。

备注:oops在中断上下文发生时,内核无法继续运行,系统就死机了。如果oops发生在idle进程(0号进程)和init进程(1号进程)时,系统也会死机,因为内核缺少这两个重要的进程根本无法工作。不过,要是oops在其它进程运行时发生,内核就会尝试杀死该进程并尝试继续执行。

内核发布oops时。会像终端上输出错误信息,输出寄存器中保存的信息并输出可供跟踪的回溯资料。通过发送完oops后,内核会处于一种不稳定状态,系统死机重启。

用bt命令查看:显示一个内核堆栈回溯。如果没有给出参数,则将显示当前上下文的堆栈跟踪。
RIP为造成内核崩溃的指令。
在这里插入图片描述

总结

本文知识简单的描述了kdump和crash的原理,安装以及使用方法。

参考资料

https://en.wikipedia.org/wiki/Kdump_(Linux)
https://blog.csdn.net/zhangskd/article/details/38084337
https://blog.csdn.net/pwl999/article/details/118418242
https://www.jianshu.com/p/ad03152a0a53
https://blog.csdn.net/rikeyone/article/details/105991074
https://zhuanlan.zhihu.com/p/104384020
https://blog.csdn.net/lx555222/article/details/110198405
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s3-proc-sys-kernel
https://zhuanlan.zhihu.com/p/94254585

<think>好的,用户现在想了解如何使用kdump进行调试。我之前已经回答过关于ftrace的问题,现在需要转向kdump。首先,我需要回忆kdump的基本概念和它在Linux内核调试中的作用。kdump主要用于在内核崩溃时捕获内存转储,这对于分析崩溃原因非常重要。接下来,我需要考虑用户可能的背景。他们可能是系统管理员或开发人员,遇到内核崩溃的问题,需要利用kdump来获取崩溃时的内存信息。 用户的需求可能包括如何配置kdump、如何触发崩溃转储,以及如何分析生成的vmcore文件。此外,用户可能对相关的工具(如crash工具)不太熟悉,需要详细的使用步骤。我需要确保覆盖这些方面,同时提供实际的操作示例,帮助他们逐步完成配置和分析过程。 我需要检查是否有常见的配置错误或注意事项需要提及,比如内存保留问题,或者不同发行版之间的配置差异。例如,CentOS和Ubuntu在kdump配置上可能有不同的包管理工具和配置文件路径。此外,还要提醒用户在生产环境中谨慎操作,避免误触发系统崩溃。 另外,用户可能对如何分析vmcore文件感到困惑,所以需要详细说明使用crash工具的基本命令,比如如何加载内核和vmcore,如何查看堆栈跟踪、寄存器状态等。还要考虑是否提到高级分析技巧,比如查找特定符号或跟踪任务状态,但需要保持回答的简洁性,避免信息过载。 最后,我需要确保回答结构清晰,分步骤讲解,每个部分都有示例代码和解释,这样用户能够按照步骤操作。同时,注意事项和常见问题也需要突出显示,帮助用户避免常见陷阱。可能还需要对比kdump与其他调试工具(如ftrace)的不同使用场景,帮助用户理解何时使用kdump更合适。</think>#### 一、kdump 核心机制解析 ```text [崩溃转储原理] │ ├── 主内核(Production Kernel): 运行中的业务系统 └── 备内核Crash Kernel): 保留内存区域,主内核崩溃时接管系统 ├── 内存转储触发机制 ├── /proc/vmcore 生成 └── 转储文件保存(vmcore) ``` --- #### 二、环境配置步骤 ##### 1. **内核启动参数配置** ```bash # 编辑grub配置文件(以CentOS为例) vi /etc/default/grub GRUB_CMDLINE_LINUX="crashkernel=256M" # 更新grub配置 grub2-mkconfig -o /boot/grub2/grub.cfg ``` **参数说明**: - `crashkernel=256M`:保留256MB内存用于崩溃内核 - 推荐值:物理内存≤2GB时保留128M,>2GB时保留256-512M ##### 2. **安装必要组件** ```bash # RedHat/CentOS yum install kexec-tools crash # Ubuntu/Debian apt install kdump-tools crash ``` ##### 3. **服务状态验证** ```bash systemctl status kdump # 正常输出应显示 active (exited) ``` --- #### 三、核心操作流程 ##### 1. **手动触发崩溃(测试环境)** ```bash # 方法1:SysRq触发 echo c > /proc/sysrq-trigger # 方法2:内核panic echo 1 > /proc/sys/kernel/sysrq echo o > /proc/sysrq-trigger # 立即重启(慎用!) ``` ##### 2. **转储文件定位** ```text 默认存储路径: ├── /var/crash/YYYY-MM-DD-HH:MM/vmcore └── /var/crash/YYYY-MM-DD-HH:MM/vmcore-dmesg.txt ``` ##### 3. **分析工具准备** ```bash # 安装调试符号包(示例为CentOS) debuginfo-install kernel-$(uname -r) # Ubuntu需要配置符号源 codename=$(lsb_release -cs) echo "deb http://ddebs.ubuntu.com ${codename} main restricted" > /etc/apt/sources.list.d/ddebs.list ``` --- #### 四、crash 工具深度分析 ##### 1. **基础会话启动** ```bash crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/.../vmcore ``` **界面示例**: ```text crash> sys KERNEL: /usr/lib/debug/lib/modules/3.10.0-1160.el7.x86_64/vmlinux DUMPFILE: /var/crash/202309011200/vmcore [PARTIAL DUMP] CPUS: 4 DATE: Mon Sep 1 12:00:45 2023 ``` ##### 2. **关键调试命令** ```text [内存分析] │ ├── bt : 显示崩溃时堆栈回溯 ├── log : 查看内核日志缓冲区 ├── kmem -i : 显示内存使用统计 └── vm -p : 进程虚拟内存分析 [进程分析] │ ├── ps : 显示所有进程状态 ├── task : 查看特定任务结构体 └── waitq : 分析等待队列 ``` ##### 3. **典型问题定位** **案例1:空指针解引用分析** ```text crash> bt -f PID: 14321 TASK: ffff88003d4d8000 CPU: 2 COMMAND: "buggy_driver" #0 [ffff88003d4d9d50] crash_kexec at ffffffff8105c7d9 #1 [ffff88003d4d9dc0] oops_end at ffffffff8152d3e8 #2 [ffff88003d4d9df0] no_context at ffffffff81053b34 #3 [ffff88003d4d9e40] __bad_area_nosemaphore at ffffffff81053e65 #4 [ffff88003d4d9e90] bad_area at ffffffff810540d3 #5 [ffff88003d4d9ec0] __do_page_fault at ffffffff81054567 #6 [ffff88003d4d9f50] do_page_fault at ffffffff81533d1e #7 [ffff88003d4d9f80] page_fault at ffffffff81530668 [exception RIP: unknown or invalid address] RIP: 0000000000000000 RSP: ffff88003d4d9f90 RFLAGS: 00010246 ``` --- #### 五、高级调试技巧 ##### 1. **符号地址解析** ```text crash> sym 0xffffffff8105c7d9 ffffffff8105c7d9 (T) crash_kexec /usr/src/debug/kernel-3.10.0/linux-3.10.0-1160.el7.x86_64/kernel/kexec_core.c: 1024 ``` ##### 2. **数据结构遍历** ```text crash> list task_struct.thread_group -s task_struct.comm,pid -h 0xffff88003d4d8000 ffff88003d4d8000 comm = "buggy_driver" pid = 14321 ``` ##### 3. **寄存器状态分析** ```text crash> irq CPU 0: No irq stack for cpu 0 CPU 1: IRQ: 0 SIE: 00000000 CIE: ffff88003f800000 CPU 2: IRQ: timer SIE: 00000008 CIE: ffff88003f800000 ``` --- #### 六、生产环境最佳实践 1. **自动化配置**: ```bash # 配置自动转储保存到NFS echo "nfs mynas:/crash_dumps" > /etc/kdump.conf ``` 2. **转储文件压缩**: ```bash # 修改kdump配置文件 core_collector makedumpfile -c --message-level 1 -d 31 ``` 3. **内存过滤策略**: ```text # /etc/kdump.conf -d 31 # 过滤页缓存等非必要内存页 ``` 4. **云环境适配**: ```bash # AWS EC2 特殊配置 echo "ext4 /dev/xvda1" > /etc/kdump.conf ``` --- #### 七、常见问题排查 ##### 问题1:crashkernel内存预留失败 **现象**: `dmesg | grep -i crash` 显示 "crashkernel reservation failed" **解决方案**: ```bash # 调整内存分配方式 crashkernel=256M,high crashkernel=128M,low ``` ##### 问题2:vmcore文件不完整 **检测方法**: ```bash makedumpfile --check /var/crash/.../vmcore ``` **修复步骤**: ```bash # 重新配置转储级别 echo "-d 31" > /etc/kdump.conf systemctl restart kdump ``` --- > **关键注意事项**: > 1. 预留内存不足时系统启动会失败,需通过控制台调整grub参数 > 2. 虚拟机环境需启用嵌套虚拟化支持 > 3. 转储文件分析需要严格匹配内核版本和调试符号 > 4. 生产环境触发崩溃前需确认业务影响范围 ```mermaid graph TD A[内核崩溃事件] --> B{kdump机制激活} B -->|成功| C[启动捕获内核] C --> D[生成vmcore] D --> E[存储到本地/NFS] E --> F[使用crash分析] B -->|失败| G[系统重启无转储] F --> H[定位错误函数] H --> I[分析寄存器状态] I --> J[检查内存泄露] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值