Linux Core Dump 配置与分析指南

Linux Core Dump 配置与分析指南

本文介绍 Linux 下 Core Dump 的含义、作用,以及如何配置生成 core 文件、如何用 GDB 分析崩溃现场,并给出常见问题与避坑建议。便于在段错误、内存越界等难以复现的线上崩溃场景中快速定位问题。

目录

[一、什么是 Core Dump](#一、什么是 Core Dump)

[二、如何配置 Core Dump](#二、如何配置 Core Dump)

[三、如何用 GDB 分析](#三、如何用 GDB 分析)

四、常见问题与避坑

小结与延伸阅读

一、什么是 Core Dump

Core Dump (核心转储)是程序异常终止 (如崩溃、收到某些信号)时,操作系统将进程的内存、寄存器、调用栈等状态写入磁盘所生成的文件,相当于崩溃瞬间的"现场快照"。

Core 文件通常包含(示意):

复制代码

┌─────────────────────────────────────────────────┐

│ Core 文件内容(供 GDB 等工具解析) │

├─────────────────────────────────────────────────┤

│ 进程内存镜像 │ 堆、栈、数据段、代码段等 │

│ 寄存器状态 │ PC、SP、通用寄存器等 │

│ 元数据 │ 信号编号、可执行路径、线程信息等 │

└─────────────────────────────────────────────────┘

GDB 据此还原崩溃时刻的调用栈、变量和寄存器,从而定位崩溃原因。

1.1 作用

作用

说明

精准定位

结合 GDB 可查看崩溃时的调用栈、变量、寄存器,定位到具体代码行

应对难复现问题

线上或压测中偶发段错误、内存越界等,无需当场复现即可事后分析

告别"盲猜"

有完整现场,便于区分是空指针、越界、栈溢出还是其他原因

1.2 典型触发场景

进程收到下列信号且未捕获、未忽略 时,默认行为为终止并可能生成 core(取决于 ulimit -c 与 core_pattern):

信号

含义

常见原因

SIGSEGV (11)

段错误

空指针解引用、非法内存访问、栈溢出

SIGABRT (6)

主动中止

abort()、断言失败、C++ std::terminate

SIGBUS (7)

总线错误

未对齐访问、映射失败后的访问等

SIGFPE (8)

算术异常

除零、整数溢出等

SIGILL (4)

非法指令

损坏的代码、不兼容的指令集

生成流程概览(配置正确时):

复制代码

进程崩溃(收到上述信号)

内核执行信号默认行为(终止进程)

检查 ulimit -c 是否允许生成 core

┌────┴────┐

│ 允许 │ 禁止 → 不生成 core

▼ │

按 core_pattern 决定路径与文件名

将进程内存、寄存器、栈等写入 core 文件

二、如何配置 Core Dump

2.1 开启 core 文件生成与大小限制

bash

复制代码

# 查看当前限制(若为 0 则不会生成 core 文件)

ulimit -c

# 解除大小限制,允许生成任意大小的 core 文件(当前 shell 及子进程生效)

ulimit -c unlimited

若需持久生效 ,可在用户 shell 配置(如 ~/.bashrc)中写入 ulimit -c unlimited,或在 systemd 服务中通过 LimitCORE=infinity 等配置。

2.2 自定义 core 文件路径与命名

通过 /proc/sys/kernel/core_pattern 指定 core 文件的保存路径和文件名格式:

bash

复制代码

# 查看当前配置

cat /proc/sys/kernel/core_pattern

# 临时修改(需 root)

echo "/var/coredump/core-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern

常用占位符:

占位符

含义

%e

可执行文件名

%p

PID

%t

时间戳(通常为 Unix 时间)

%h

主机名

%s

导致 dump 的信号编号

示例:/var/coredump/core-%e-%p-%t 会生成如 core-myapp-12345-1640000000 的文件。需确保目标目录存在且进程有写权限。

2.3 systemd 服务中开启 Core Dump(持久生效)

通过 systemd 管理的服务若需在崩溃时生成 core,可在 unit 中设置 LimitCORE=infinity(或足够大的字节数),并视情况配合 core_pattern 使用。

示例一:在 service 文件里直接写 limit

ini

复制代码

[Unit]

Description=My Demo Service

After=network.target

[Service]

Type=simple

ExecStart=/usr/local/bin/myapp

# 允许生成任意大小的 core 文件

LimitCORE=infinity

# 可选:限制仅本服务生效,不继承 system 默认

# LimitCORE=infinity

[Install]

WantedBy=multi-user.target

示例二:用 drop-in 覆盖已有服务的 limit(不改原 unit 文件)

bash

复制代码

# 创建 drop-in 目录

sudo mkdir -p /etc/systemd/system/myapp.service.d/

# 创建 conf 文件,只写要覆盖的项

sudo tee /etc/systemd/system/myapp.service.d/coredump.conf << 'EOF'

[Service]

LimitCORE=infinity

EOF

# 重载并重启服务

sudo systemctl daemon-reload

sudo systemctl restart myapp.service

示例三:确认生效

bash

复制代码

# 查看该进程的 core 限制(PID 需替换为实际值)

cat /proc//limits | grep "core file size"

# 期望看到:Max core file size unlimited unlimited

与 core_pattern 的配合 :LimitCORE 只控制"是否允许生成、最大多大";core 写到哪里、叫什么名字仍由 /proc/sys/kernel/core_pattern 决定。若希望 core 落盘到固定目录,需事先用 sysctl 或 echo ... > /proc/sys/kernel/core_pattern 配置好路径,并保证该目录存在且进程(或 kernel)有写权限。

2.4 配置要点小结

项目

说明

ulimit -c

为 0 则不生成;设为 unlimited 或足够大的数字以允许生成

core_pattern

路径需存在、可写;可用占位符区分不同进程与时间

权限

若 core 含敏感信息,应限制目录权限与访问范围

配置检查清单(生成 core 前建议确认):

检查项

命令或方法

当前 shell 的 core 限制

ulimit -c(应为 unlimited 或非 0)

系统 core 路径与命名

cat /proc/sys/kernel/core_pattern

目标目录是否存在、可写

ls -la /var/coredump(或你配置的目录)

持久化(如 systemd 服务)

见上文 2.3 systemd 示例;或启动脚本中 ulimit -c unlimited

三、如何用 GDB 分析

3.1 加载程序与 core 文件

bash

复制代码

gdb <可执行程序>

# 示例

gdb ./myapp /var/coredump/core-myapp-12345-1640000000

3.2 常用 GDB 命令

命令

说明

bt(backtrace)

查看崩溃时的完整调用栈,快速定位出错函数与层级

bt full

在每帧中打印局部变量等信息

info registers

查看寄存器

frame N

切换到栈帧 N

list

查看当前帧附近源码

print 变量

打印变量值(需带调试符号)

3.3 分析流程简述

推荐步骤可概括为:

复制代码

gdb <程序>

bt / bt full → 定位崩溃栈帧与行号

frame N → 切换到怀疑的帧

print 变量 → 查看指针、关键变量

list → 查看源码上下文

判断原因(空指针 / 越界 / 双重释放 / 栈溢出等)→ 修复代码

步骤

目的

bt

看完整调用栈,找到崩溃发生在哪一帧、哪一行

frame N

切换到第 N 帧,便于查看该帧的局部变量

print

查看指针是否为空、下标是否越界、对象是否已释放

list

查看当前帧附近源码,配合行号理解逻辑

注意 :若编译时未加 -g,GDB 无法显示符号名和行号,只能看到地址,分析会困难很多。

3.4 GDB 分析速查表

场景

常用命令

看调用栈

bt、bt full

看当前帧源码

frame、list

看变量/寄存器

print 变量、info registers

看线程

info threads、thread N

看内存

x/Nx 地址(N 为单位数)

四、常见问题与避坑

4.1 没有生成 core 文件

可能原因

排查与处理

ulimit -c 为 0

当前 shell 执行 ulimit -c unlimited;或检查 systemd/启动脚本中的 limit 配置

目标目录无写权限

检查 core_pattern 中的目录是否存在、进程用户是否有写权限

core_pattern 路径错误

用 cat /proc/sys/kernel/core_pattern 确认,路径中的目录需事先创建

磁盘空间不足

确保目标分区有足够空间;core 文件可能较大

4.2 GDB 中无符号、无行号

原因:可执行文件未带调试信息。

解决 :编译时加上 -g (如 gcc -g -O0 ...),发布时可保留带符号的副本专门用于分析 core,或使用 strip 分离符号文件。

4.3 生产环境风险

风险

建议

敏感信息

core 文件可能包含内存中的密码、密钥等,需严格限制访问与保留时间

磁盘占用

大进程 core 可能数 GB,需监控磁盘与清理策略

性能与稳定性

生成大 core 时可能卡顿,建议仅在测试或受控环境开启,或按需开启

4.4 问题与对策速查表

现象

可能原因

对策

完全没有 core 文件

ulimit -c 为 0;目录不存在或无写权限;core_pattern 错误

见 4.1;逐项检查配置清单

GDB 中无符号、无行号

未带调试信息编译

重新编译加 -g,或保留带符号副本用于分析

core 与可执行文件不匹配

程序已更新,core 是旧版本崩溃

用与崩溃时一致的可执行文件(或同版本 + 符号)加载 core

多线程崩溃难以定位

需看其他线程栈

GDB 中 info threads、thread N、bt 结合分析

小结与延伸阅读

小结

Core Dump 是进程崩溃时的内存与状态快照,用于事后用 GDB 分析调用栈与变量,精准定位段错误、越界等问题。

配置 :ulimit -c unlimited 解除大小限制;通过 core_pattern 指定路径和命名(如 %e-%p-%t)。

分析 :gdb <程序> ,用 bt 看调用栈,用 frame/print/list 查变量与源码;编译时加 -g 才能看到符号和行号。

避坑:检查 ulimit、目录权限与 core_pattern;生产环境注意敏感信息与磁盘占用,建议在测试或受控环境使用。

延伸阅读

signal(7) 、core(5):Linux man 手册中关于信号与 core 的说明。

GDB 手册:backtrace、examining stack、symbols 等章节。

同目录 Android_Tombstone崩溃日志详解:Android 侧的崩溃快照与分析思路。

根据 Linux Core Dump 相关教程与实操整理。