coredump和kdump
下面给你一份完整文档,包含你之前的内容,并且我已经把“运行中进程如何修改 ulimit 触发 coredump”补充完整、按原结构嵌入,且后续内容保持不变。
完整文档:coredump + kdump + 非官方/无 debuginfo 分析(含运行中进程修改 ulimit)
1. Core dump(用户态进程崩溃)
1.1 原理(必须理解)
-
进程崩溃时(SIGSEGV/SIGABRT 等),内核会检查该进程的
RLIMIT_CORE(即 core size 限制)。 -
若允许生成 core,则内核会将进程内存快照写到文件(core 文件),并写入一些元信息(寄存器、线程、映像映射等)。
-
生成 core 时涉及:
-
ulimit -c(进程级 rlimit) -
/proc/sys/kernel/core_pattern(core 文件命名/位置/管道) -
运行目录权限 / 指定目录权限
-
systemd 的
LimitCORE(systemd 管理的进程)
-
补充:运行中的进程怎么修改 ulimit 触发 coredump(完整)
-
ulimit修改的是 当前 shell 及其子进程的 rlimit。
对于 已经运行的进程,其 rlimit 已在启动时固定,因此 普通ulimit -c unlimited不会影响已运行进程。 -
运行中进程要修改 core limit,需要使用
prlimit或系统级机制(systemd),否则只能重启进程。
方式 A:使用 prlimit(对运行中进程生效,推荐)
sudo prlimit --pid <pid> --core=unlimited
验证:
cat /proc/<pid>/limits | grep core
输出应为:
Max core file size unlimited unlimited bytes
触发 core(模拟崩溃):
kill -SIGABRT <pid>
或程序实际崩溃(SIGSEGV 等)。
方式 B:如果进程由 systemd 管理(必须修改 systemd)
sudo mkdir -p /etc/systemd/system/<service>.service.d
sudo tee /etc/systemd/system/<service>.service.d/override.conf <<EOF
[Service]
LimitCORE=infinity
EOF
sudo systemctl daemon-reload
sudo systemctl restart <service>
验证:
cat /proc/<pid>/limits | grep core
方式 C:不修改 core limit,直接生成 core(不让进程崩溃)
gcore -o /tmp/core.<pid> <pid>
或:
gdb -p <pid> -batch -ex "generate-core-file /tmp/core" -ex "detach" -ex "quit"
1.2 自动触发(进程崩溃自动生成 core)
1.2.1 全局配置(推荐)
1)设置 core 文件大小无限制:
sudo tee /etc/security/limits.d/99-core.conf <<EOF
* soft core unlimited
* hard core unlimited
EOF
2)设置 core 生成路径与命名:
sudo sysctl -w kernel.core_pattern=/tmp/core.%e.%p.%t
3)确保目录可写:
sudo mkdir -p /tmp/coredumps
sudo chmod 777 /tmp/coredumps
sudo sysctl -w kernel.core_pattern=/tmp/coredumps/core.%e.%p.%t
4)验证:
ulimit -c
cat /proc/sys/kernel/core_pattern
1.2.2 systemd 管理进程(必须设置)
systemd 默认可能限制 core dump。
创建配置:
sudo mkdir -p /etc/systemd/system/<service>.service.d
sudo tee /etc/systemd/system/<service>.service.d/override.conf <<EOF
[Service]
LimitCORE=infinity
EOF
sudo systemctl daemon-reload
sudo systemctl restart <service>
1.3 手动触发 core(不崩溃也能生成)
方式 A:向进程发送 SIGABRT(模拟崩溃)
kill -SIGABRT <pid>
方式 B:gcore(生成 core,不影响进程运行)
gcore -o /tmp/core.dump <pid>
方式 C:使用 ptrace / 调试器强制生成(更底层)
gdb -p <pid> -batch -ex "generate-core-file /tmp/core" -ex "detach" -ex "quit"
1.4 分析 coredump(gdb)
1.4.1 基本流程
gdb <binary> <corefile>
常用命令:
bt # 查看调用栈
info threads # 查看线程
thread <n> # 切换线程
frame <n> # 进入栈帧
info locals # 查看局部变量
p <var> # 打印变量
info registers # 寄存器
x/20x $sp # 查看栈内容
1.4.2 关键点(崩溃定位)
-
先
bt找到崩溃帧(通常是 frame 0) -
查看寄存器
info registers -
查看指针是否为 NULL / 非法地址
-
找到调用链(调用者参数是否异常)
1.5 符号/调试信息(关键)
-
没有 debug 符号,
gdb只能看到地址,无法看到源代码和变量名。 -
需要
-g编译或保留 debug 符号。
1.5.1 编译带 debug(推荐)
gcc -g -O0 -o app app.c
1.5.2 分离 debug 符号(生产环境常用)
objcopy --only-keep-debug app app.debug
strip --strip-debug app
objcopy --add-gnu-debuglink=app.debug app
1.5.3 没有 debuginfo 也能做的事
-
通过
addr2line把地址转换为函数/行(如果有符号表) -
通过
readelf -s查看符号表(如果未 strip) -
通过
objdump -d反汇编(无 debug 也能分析)
示例:
addr2line -e app 0x400abc
如果可执行文件被 strip,则需要 app.debug 或重新编译。
1.6 非官方/自定义编译的场景(没有 debuginfo)
1.6.1 只能拿到地址的情况怎么办?
1)用 readelf -s 找到函数符号(如果保留符号)
2)用 objdump -d 反汇编
3)用 addr2line 反查地址对应函数
例如:
objdump -d app | grep -n "400abc"
如果是动态库崩溃:
readelf -Ws libxxx.so | grep <symbol>
1.6.2 通过映射关系定位
core 文件中包含进程的映射表(mmap),可以看到各个库的基地址:
info proc mappings
然后结合 nm / objdump 的偏移,计算实际地址:
实际地址 = 基址 + 偏移
2. kdump(内核崩溃 / kernel panic)
2.1 kdump 原理(必须理解)
-
当 Linux 内核发生 panic 时,主内核会重启,但在重启前会启动一个 crash kernel(小内核)。
-
crash kernel 会在 保留的内存区域 中运行,读取主内核的内存镜像(vmcore),并保存到磁盘或网络。
-
vmcore 相当于“内核级的 core dump”。
关键点:
-
需要预留 crashkernel 内存(boot 参数)
-
需要 kexec-tools/kdump 服务
-
需要可用的 vmlinux(带符号的内核映像)
2.2 自动触发 kdump(内核 panic 自动产生 vmcore)
2.2.1 安装与配置(以常见发行版为例)
sudo yum install -y kexec-tools # RHEL/CentOS
sudo apt-get install -y kdump-tools # Debian/Ubuntu
2.2.2 设置 crashkernel(必须)
在 grub 中添加:
crashkernel=256M
并更新 grub:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/CentOS
sudo update-grub # Debian/Ubuntu
2.2.3 启动 kdump 服务
sudo systemctl enable kdump
sudo systemctl start kdump
2.2.4 配置 vmcore 存放位置
编辑 /etc/kdump.conf:
path /var/crash
core_collector makedumpfile -c --message-level 1 -d 31
2.3 手动触发 kdump(强制内核 panic)
2.3.1 通过 sysrq 强制 panic(常用)
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
系统会直接 panic 并触发 kdump(如果配置正确)。
2.3.2 通过 sysctl 触发 panic(更“温和”)
echo 1 > /proc/sys/kernel/panic_on_oops
echo oops > /proc/sysrq-trigger
2.4 分析 kdump(vmcore)
2.4.1 关键工具:crash
crash 是最常用的分析工具。
crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/<vmcore>
常用命令:
bt # 内核调用栈
ps # 查看进程列表
struct # 查看结构体内容
vm # 查看内存
log # 查看日志
2.4.2 如果没有 vmlinux(无符号表)
-
crash 需要 vmlinux(带符号)才能解析符号。
-
如果只有 bzImage 或 vmlinuz,必须从源码编译或从发行版获取 debug kernel。
3. 非官方 kernel / 没有 debuginfo 的分析策略(重点)
3.1 Core dump 没有 debug 信息时(用户态)
方式 1:用符号表(如果存在)
即使没有 debug 信息,只要未 strip 或保留符号表:
nm -C app | head
readelf -s app | grep " FUNC "
方式 2:没有符号表但有地址
只能用反汇编 + 经验:
-
用
objdump -d看代码逻辑 -
根据崩溃地址推断函数(结合
info proc mappings) -
找到附近的汇编指令和调用关系
方式 3:通过日志/栈回溯结合上下文
-
通过
dmesg、应用日志 -
通过
strace、ltrace -
通过复现脚本定位
3.2 Kdump 没有 vmlinux 或没有符号表
这是最难的情况。可用策略:
方式 1:从 kernel 源码重新编译(建议)
-
取得相同版本的 kernel 源码
-
使用相同配置
.config -
生成 vmlinux(带符号)
-
用 crash 分析 vmcore
方式 2:用 makedumpfile / crash 的最小分析
即使没有符号,也可以:
-
通过
crash的bt -a或bt -d看到地址 -
结合
System.map(符号地址表)定位到函数
方式 3:利用 System.map(符号表)
如果有 System.map,可以解析:
grep " some_function" System.map
然后结合 crash 的地址定位。
4. 你需要的“完整落地”执行清单
4.1 生成 core(推荐配置)
# 1) 全局允许
sudo tee /etc/security/limits.d/99-core.conf <<EOF
* soft core unlimited
* hard core unlimited
EOF
# 2) core pattern
sudo mkdir -p /tmp/coredumps
sudo chmod 777 /tmp/coredumps
sudo sysctl -w kernel.core_pattern=/tmp/coredumps/core.%e.%p.%t
# 3) 对 systemd 服务
sudo mkdir -p /etc/systemd/system/<service>.service.d
sudo tee /etc/systemd/system/<service>.service.d/override.conf <<EOF
[Service]
LimitCORE=infinity
EOF
sudo systemctl daemon-reload
sudo systemctl restart <service>
4.2 分析 core(关键步骤)
gdb /path/to/binary /tmp/coredumps/core.<name>.<pid>.<time>
bt
info threads
thread <n>
frame 0
info locals
p <var>
4.3 生成 kdump(推荐配置)
# 1) 安装
sudo yum install -y kexec-tools
# 2) crashkernel
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# 需要在 /etc/default/grub 添加 crashkernel=256M
# 3) 启动 kdump
sudo systemctl enable kdump
sudo systemctl start kdump
# 4) 手动触发
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
4.4 分析 vmcore
crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/<vmcore>
bt
ps
log
5. 你需要补充的关键信息(我可以给你定制脚本/配置)
为了给你“完全适配你环境”的完整方案,我需要你补充以下信息:
-
你的 Linux 发行版(CentOS/Ubuntu/Debian/Alpine/其他)
-
你的程序是 systemd 启动还是手动启动
-
你的内核版本
uname -r -
你是否可以安装 kexec-tools/kdump-tools
-
你是否能编译内核/程序(是否可获取源码)
浙公网安备 33010602011771号