蔚淦丞
发布于 2026-11-05 / 3 阅读
0
0

Linux 常见异常信号速查与辨析

Linux 常见异常信号速查与辨析

是什么

Linux 内核在检测到进程违规操作时,会向该进程发送对应的异常信号(Signal)。理解这些信号的含义和区别,是定位崩溃、调试内存问题和编写健壮程序的基础。本文梳理开发中最常遇到的 7 种异常信号,重点辨析容易混淆的信号对。

信号速查表

信号 编号 全称 触发原因 典型场景
SIGSEGV 11 Segmentation Violation 访问未映射或无权限的内存地址 空指针解引用、野指针、数组越界、栈溢出
SIGBUS 7 Bus Error 硬件层面的内存访问错误 内存未对齐访问、mmap 文件被截断后访问、物理内存故障
SIGABRT 6 Abort 进程主动调用 abort() 终止 assert 失败、glibc/ASan 检测到堆损坏(double-free 等)
SIGFPE 8 Floating-Point Exception 算术运算异常 整数除以零、浮点溢出/无效操作
SIGILL 4 Illegal Instruction CPU 无法识别当前指令 二进制损坏、跳转到非代码区域、不支持的指令集
SIGTRAP 5 Trace/Breakpoint Trap 断点或单步调试陷阱 GDB 断点、__builtin_trap()、sanitizer 内部检查点
SIGSYS 31 Bad System Call 非法或不存在的系统调用 seccomp 沙箱拦截、glibc 与内核版本不匹配

以上信号的默认动作均为终止进程并生成 core dump(受 ulimit 限制)。SIGKILL(9) 和 SIGSTOP(19) 不可捕获,其余可通过 sigaction() 自定义处理。

核心辨析:三组易混淆信号

SIGSEGV vs SIGBUS

这是最常混淆的一对。本质区别在于错误发生的层级不同:

  • SIGSEGV:MMU 页表层面拒绝。地址在逻辑上就不该访问(未映射、权限不足)。x86/ARM 上绝大多数内存访问错误都是 SEGV。
  • SIGBUS:硬件总线层面失败。地址在页表中合法,但物理总线无法完成传输。典型触发条件:
    • ARM/RISC-V 上的未对齐访问(x86 通常自动处理不报错)
    • mmap 的文件被其他进程截断后继续访问
    • 物理内存硬件故障

实践判断:x86 上遇到 SIGBUS 优先考虑 mmap 文件问题;ARM 上优先考虑对齐问题;其余情况大概率是 SIGSEGV。

SIGABRT vs SIGSEGV

  • SIGABRT 是软件主动自杀:运行时库(glibc、ASan、assert 宏)检测到不可恢复的错误后,故意调用 abort() 发出。收到 ABRT 意味着"程序自己发现了问题并选择终止"。
  • SIGSEGV 是硬件被动捕获:CPU/MMU 直接报错,程序本身没有意识到出了问题。

实践意义:看到 SIGABRT 应优先查看 stderr 输出(glibc/ASan 通常会打印详细诊断信息);看到 SIGSEGV 则需要 core dump + GDB 回溯。

SIGFPE 的名称陷阱

SIGFPE 全称含 “Floating-Point”,但实际涵盖所有算术异常,包括整数除以零。历史上浮点异常是最常见的算术错误,信号名沿用至今。不要因为名字里带"浮点"就忽略整数运算的可能性。

ASan 与信号的关系

AddressSanitizer 会将大部分本应触发 SIGSEGV/SIGBUS 的错误转化为 SIGABRT,并在 abort 前输出结构化诊断报告(含调用栈、内存布局、分配/释放历史)。这就是为什么开启 ASan 后看到的通常是 ABRT 而非 SEGV——ASan 抢先检测到了问题并主动终止。

调试流程建议

  1. 确认信号类型:dmesg | tail 或 /proc/<pid>/status 中的 SigCgt/SigIgn 掩码
  2. 获取 core dump:ulimit -c unlimited + coredumpctl list
  3. 分析现场:gdb ./binary core → bt full 查看完整调用栈
  4. 启用 sanitizer:编译时加 -fsanitize=address 获得更精确的错误定位
  5. 区分环境:x86 vs ARM 对 SIGBUS 的行为差异显著,注意目标架构

未完全理解的部分

  • SIGBUS 在不同架构上的精确触发条件仍有差异,需查阅具体 CPU 手册
  • seccomp-bpf 返回 SIGSYS 时的 errno 传递机制尚未深入研究
  • 实时信号(SIGRTMIN~SIGRTMAX)在应用层的使用场景和注意事项待补充

评论