一文搞懂应用程序 core dump 和内核 core dump

303 阅读5分钟

调试 应用程序 core dump内核 core dump (kdump/vmcore) 需要完全不同的工具链和流程。下面我从 原理 → 准备工作 → 调试流程 → 典型场景 全面讲解。


1. 应用程序 core dump 调试

应用程序 core dump 是指 用户态进程 崩溃后生成的内存镜像,常见原因有 SIGSEGVSIGABRT 等。


1.1 典型触发场景

崩溃原因常见触发信号典型表现
空指针/非法内存访问SIGSEGV (11)段错误,dmesg 中有 Segfault
除零、浮点异常SIGFPE (8)数学运算崩溃
调用 abort()SIGABRT (6)进程主动中止
内存越界、UAFSIGBUS (7)总线错误
断言失败SIGABRT (6)程序代码 assert() 触发

1.2 Core 文件生成与收集

(1) 检查系统是否允许生成 core

ulimit -c
  • 输出 0:不生成 core,需要打开

  • 临时启用:

    ulimit -c unlimited
    

(2) 设置 core 文件命名与路径

通过 /proc/sys/kernel/core_pattern 配置,例如:

cat /proc/sys/kernel/core_pattern

常见输出:

|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %e

说明:如果输出以 | 开头,表示 core dump 会交给 systemd-coredump 处理,并压缩到 /var/lib/systemd/coredump/

若想存储到自定义目录:

sudo sysctl -w kernel.core_pattern="/var/core/core.%e.%p.%t"

(3) systemd-coredump 方式收集

直接用:

coredumpctl list
coredumpctl info <PID>
coredumpctl gdb <PID>
  • list:查看所有 core dump 记录
  • info:查看 core dump 详情
  • gdb:直接进入 GDB 调试(无需手动找 core 文件)

1.3 调试核心步骤

(1) 准备符号文件

必须确保可执行程序是带调试符号的:

gcc -g -O0 myapp.c -o myapp

如果是发行版程序,安装 debuginfo 包,例如 SLES:

zypper install myapp-debuginfo

(2) 启动 gdb

假设 core 文件是 core.12345,可执行文件是 myapp

gdb myapp core.12345

(3) 常用调试命令

命令作用
bt打印崩溃线程的调用栈
thread apply all bt打印所有线程的调用栈
info locals查看当前函数局部变量
info registers查看寄存器状态
frame N切换到栈帧 N
list查看崩溃点附近的源码
p var打印变量值
x/16x addr查看内存内容

示例:

(gdb) bt
#0  0x00007ffff7a3345d in strlen () from /lib64/libc.so.6
#1  0x0000000000401172 in process_data (str=0x0) at main.c:25
#2  0x00000000004011d5 in main () at main.c:40

结论:调用 strlen(NULL) 导致 SIGSEGV。


(4) 多线程分析

如果程序多线程,必须检查所有线程状态:

(gdb) info threads
  Id   Target Id         Frame 
* 1    Thread 0x7ffff7fc2700 (LWP 12345) "myapp" strlen ()
  2    Thread 0x7ffff77c1700 (LWP 12346) __pthread_cond_wait ()

(5) 高级工具

  • gcore:运行中生成 core dump

    gcore <pid>
    
  • valgrind:检测内存越界、内存泄漏

    valgrind --leak-check=full ./myapp
    

1.4 应用 core dump 调试总结流程

  1. 确认 core 文件存在,使用 coredumpctl/proc/sys/kernel/core_pattern 检查。

  2. 确认可执行文件和符号包完整。

  3. gdb myapp core.xxx 进入调试。

  4. 重点分析:

    • 崩溃线程调用栈 bt
    • 线程间死锁问题 thread apply all bt
    • 检查局部变量、内存
  5. 根据源码或逻辑定位 bug。


2. 内核 core dump (kdump/vmcore) 调试

内核 core dump 捕获的是 整个系统内核态内存,用于分析 Kernel Panic、软锁死、驱动 Bug 等问题。


2.1 典型触发场景

触发问题常见表现
驱动 Bug内核 Panic,堆栈指向特定驱动
内核 Null PointerKernel NULL pointer dereference
硬件故障NMI Panic、ECC 错误
调度死锁Soft Lockup/Hard Lockup
文件系统崩溃ext4 / xfs 内核函数触发 panic

2.2 kdump 配置与收集

  1. 安装 kdump 组件

    zypper install kdump crash
    
  2. 启用 kdump 服务

    systemctl enable kdump
    systemctl start kdump
    
  3. 配置 /etc/kdump.conf

    path /var/crash
    core_collector makedumpfile -c --message-level 1 -d 31
    
  4. 触发 panic 测试

    echo c > /proc/sysrq-trigger
    

    机器重启后,会在 /var/crash/ 下生成目录:

    /var/crash/2025-09-09-11:02/vmcore
    /var/crash/2025-09-09-11:02/vmcore-dmesg.txt
    

2.3 调试工具:crash

(1) 启动 crash

crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/2025-09-09-11:02/vmcore

注意:
vmlinux 必须是未剥离符号的内核调试文件,否则无法解析函数名。


(2) 常用命令

命令功能
bt当前 CPU 调用栈
bt -a所有 CPU 调用栈
ps查看所有进程状态
log查看内核日志
kmem查看内存信息
files查看文件句柄
mod查看加载的内核模块
irq查看中断信息
runq查看调度队列

示例:分析软锁死

crash> bt -a
PID: 0      TASK: ffffffff81a9f400  CPU: 0  COMMAND: "swapper/0"
#0 [ffff88013fc03d00] schedule at ffffffff8156c6c0
#1 [ffff88013fc03d50] schedule_timeout at ffffffff8156e1d6
#2 [ffff88013fc03dd0] worker_thread at ffffffff8159dfab

(3) 分析软锁死/Hard Lockup

cat /proc/softirqs
cat /proc/interrupts

在 crash 工具中:

irq
runq

2.4 内核调试总结流程

  1. 确认 /var/crash/ 下的 vmcore 存在。

  2. 确保对应版本的 vmlinux 调试文件。

  3. 使用 crash 打开:

    crash vmlinux vmcore
    
  4. 分析内容:

    • bt -a 检查所有 CPU 调用栈;
    • ps 检查可疑进程;
    • log 查看 panic 前的 dmesg;
    • kmem 查看内存状态。

3. 应用 core vs 内核 core 对比

特性应用 core dump内核 core dump (kdump/vmcore)
调试工具gdb / coredumpctlcrash / gdb
分析粒度单进程虚拟内存、线程栈全部 CPU、进程、内核数据结构
触发范围应用代码 bug驱动、内核调度、内存管理 bug
文件位置/var/lib/systemd/coredump/var/crash/vmcore
常见大小MB ~ 几 GB接近物理内存大小
分析难度中等高,需要深入内核知识

4. 总结流程图

             崩溃发生
                  │
         ┌────────┴─────────┐
         │                  │
  应用程序崩溃 (SIGSEGV)      Kernel Panic
         │                  │
   使用 coredumpctl           使用 kdump
         │                  │
   gdb myapp core.xxx         crash vmlinux vmcore
         │                  │
   分析线程栈/变量            分析CPU栈/调度/内存

5. 总结

  • 应用 core dump 调试:

    1. 确保 core 文件和符号文件存在。
    2. 使用 gdb 打开 gdb myapp core.xxx
    3. 核心命令:btthread apply all bt
  • 内核 core dump 调试:

    1. 启用 kdump 服务,panic 时收集 vmcore。
    2. 使用 crash vmlinux vmcore 分析。
    3. 关注所有 CPU 栈、调度、内存状态。

经验法则:

  • core.xxx.zst → 高度可能是用户态 core dump。
  • vmcore → 一定是内核 core dump。