Core 与 GDB 分析:从概念到实战
一、Core 分析解决的是什么问题
程序运行过程中,可能出现两类完全不同的问题。
第一类是程序自己记录下来的错误,例如:
连接数据库失败
文件不存在
权限不足
SQL语法错误
磁盘空间不足
这类问题一般会被写入运行日志。程序通常还能控制错误处理过程,因此日志里可能明确记录错误码、错误描述和发生时间。
第二类是程序本身突然失去正常执行能力,例如:
访问了不存在的内存地址
使用了已经释放的内存
发生除零
执行了非法指令
内部断言失败
某个动态库异常退出
线程栈溢出
程序可能来不及把详细原因写入日志,就被操作系统终止。
这时,运行日志最多可能只留下:
程序异常退出
Segmentation fault
signal 11
但我们真正想知道的是:
哪个线程出了问题?
程序执行到了哪个函数?
这个函数是被谁调用的?
当时函数参数是什么?
访问了哪个内存地址?
关键寄存器里是什么值?
崩溃发生在主程序还是动态库?
Core Dump 的作用,就是尽可能保存程序异常时的现场。
GDB 的作用,则是读取和解释这个现场。
可以先用一句话记忆:
Core 是事故现场,GDB 是勘查事故现场的工具。
二、Core Dump 是什么
Core Dump 中文常译为:
- 核心转储;
- 内存转储;
- 进程崩溃快照;
- Core 文件。
它通常是一个二进制文件。
当程序收到某些会导致异常终止的信号时,Linux 内核可以将程序当时的部分内存映像和进程状态写入 Core 文件。GDB 官方将 Core 描述为运行进程的内存映像和进程状态记录,包括寄存器值等,其主要用途是对已经崩溃的程序进行事后调试。
例如:
dmserver正在执行SQL
↓
某个线程访问非法内存
↓
CPU产生异常
↓
Linux向进程发送SIGSEGV
↓
dmserver异常终止
↓
Linux尝试生成Core文件
Core 不是普通日志,因此不能用下面的方法正常阅读:
cat core文件
vi core文件
less core文件
即使强行打开,看到的也主要是不可读的二进制内容。
Core 需要交给 GDB 等调试工具解释。
三、Core、日志和 Redo 的区别
数据库场景里,最容易把以下几种信息混在一起。
| 信息 | 记录的内容 | 主要用途 |
|---|---|---|
| 数据库运行日志 | 启停、错误、警告和运行事件 | 判断崩溃前发生过什么 |
| 操作系统日志 | OOM、磁盘、文件系统、内核和硬件信息 | 判断是否为系统层问题 |
| Core 文件 | 进程异常瞬间的内存和执行现场 | 分析进程为什么崩溃 |
| Redo 日志 | 数据库修改记录 | 实例恢复和事务一致性 |
| 数据库备份 | 数据文件的可恢复副本 | 数据库还原与恢复 |
例如,dmserver 因程序缺陷突然退出后,可能同时发生:
生成Core
→ 用来调查dmserver为什么崩溃
重新启动时读取Redo
→ 用来恢复未完成的数据写入
因此:
Core 解决“程序为什么死”,Redo 解决“程序死后数据库怎样恢复一致”。
Core 不能代替数据库备份,也不能用来还原数据。
四、GDB 是什么
GDB 全称是:
GNU Debugger
它是 GNU 提供的程序调试器。
GDB 的用途并不局限于 Core,它有三种常见工作模式。
1. 调试即将运行的程序
gdb ./core_lab
进入 GDB 后:
run
此时程序在 GDB 控制下运行。
可以:
- 设置断点;
- 单步执行;
- 查看变量;
- 修改变量;
- 查看寄存器;
- 查看内存;
- 观察函数调用。
这种方式适合开发人员调试能够复现的问题。
2. 附加到正在运行的程序
gdb -p PID
例如:
gdb -p 12345
GDB 会附加到 PID 为 12345 的进程。
这种方式可以用于分析:
- 程序卡死;
- 线程长时间等待;
- CPU 异常占用;
- 某个进程还活着,但没有响应。
不过,GDB 附加进程期间通常会暂停被调试进程,因此生产环境必须谨慎。
3. 分析已经生成的 Core
gdb 可执行文件 Core文件
例如:
gdb /dmdbms/bin/dmserver \
/dmdata/core/core-dmserver-12345
这表示:
用dmserver可执行文件及其符号信息
解释Core文件中的内存和进程状态
这就是最常见的 Core 事后分析模式。
五、为什么有了 Core,还需要原来的可执行程序
Core 里面保存的大量信息,本质上是地址和原始数据。
例如:
当前执行地址:0x00000000014a52c0
只看这个地址,我们不知道它代表什么。
GDB 需要结合对应版本的可执行文件,将地址映射成:
某个函数
某个模块
某条机器指令
可能的源代码行
GDB 在分析 Core 时,会把 Core 作为内存内容,同时从可执行文件中读取程序代码、只读段和符号信息。因此,传统 Core 通常只保存地址空间的一部分,其他内容需要从原始可执行文件补充。
理想的 Core 分析材料包括:
Core文件
+
崩溃时对应版本的可执行程序
+
对应版本的动态库
+
对应的调试符号文件
如果发生崩溃后数据库进行了升级,再拿新版本的 dmserver 分析旧 Core,可能出现:
- 函数地址对应错误;
- 堆栈无法展开;
- 函数名混乱;
- 动态库地址不匹配;
- GDB 显示大量问号;
- 分析结论不可信。
所以现场处理中,不能只保留 Core,还应尽量保留故障时的程序版本、动态库和补丁信息。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)