linxu内核的signal fault和arm内核的flault
一、情景引入
我们在分析linux或者安卓系统的coredump文件时,经常碰见SIGSEGV(段错误)、SIGBUS(总线错误)。那么这些错误和arm内核的各种硬件fault有什么关联呢?
二、基本概念
Signal Fault:这是 Linux 系统通过信号机制通知进程发生错误的一种方式。例如,SIGSEGV(段错误)、SIGBUS(总线错误)、SIGILL(非法指令)等信号都属于 Signal Fault。
ARM 内核定义了多种异常类型,用于处理硬件层面的错误情况,常见的 ARM 内核 Fault 包括:
- Data Abort:在数据访问(读取或写入)出错时触发。
- Prefetch Abort:指令预取失败时会引发该异常。
- Undefined Instruction:遇到无法识别的指令时产生。
- Bus Fault:总线访问失败,比如地址对齐错误或者外设响应超时。
三、关联机制
当 ARM 内核检测到硬件 Fault 时,会触发相应的异常处理流程。Linux 内核中的异常处理程序会捕获这些硬件异常,并将其转换为用户空间的 Signal,具体对应关系如下:
ARM 内核 Fault | Linux Signal | 常见原因 |
---|---|---|
Data Abort | SIGSEGV 或 SIGBUS | - SIGSEGV:访问未映射的内存地址 - SIGBUS:访问的地址有效,但总线传输失败(如非对齐访问) |
Prefetch Abort | SIGILL | 指令地址无效或指令格式错误 |
Undefined Instruction | SIGILL | 执行了 ARM 架构不支持的指令 |
Bus Fault | SIGBUS | 总线访问错误,例如地址未对齐、外设故障 |
SIGSEGV vs SIGBUS
这两个信号都与内存访问错误有关,但具体场景不同:
- SIGSEGV(段错误):通常是因为访问了未映射的虚拟地址。比如,解引用空指针(
*NULL
)或者访问越界的数组元素。 - SIGBUS(总线错误):更多是硬件层面的问题,例如:
- 非对齐访问(在 ARMv7-M 等架构中,某些指令要求数据地址必须对齐)。
- 访问物理设备地址时,外设响应错误。
四、映射源码解读
1. ARM 架构的异常处理核心逻辑
- 文件路径:
arch/arm/kernel/traps.c
- 关键函数:
do_DataAbort()
、do_PrefetchAbort()
、do_BusFault()
- 信号映射示例:
// 处理数据中止异常 static void do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) {struct siginfo info;...// 根据错误类型设置不同的信号if (user_mode(regs)) {info.si_signo = SIGSEGV; // 默认发送SIGSEGVinfo.si_code = SEGV_MAPERR; // 映射错误...force_sig_info(SIGSEGV, &info, current); // 向当前进程发送信号} else {die("Oops", regs, fault_code);} }
2. Bus Fault 的具体处理
- 文件路径:
arch/arm/mm/fault.c
- 关键函数:
do_bad_area()
、do_translation_fault()
- 信号映射逻辑:
// 处理无效地址访问 static int do_bad_area(unsigned long addr, unsigned int fsr,struct pt_regs *regs) {if (user_mode(regs)) {// 对用户空间地址,发送SIGSEGVkill_faulted_task(current, addr, fsr, regs, SIGSEGV);return 0;}... }
3. 非对齐访问的特殊处理
- 文件路径:
arch/arm/mm/alignment.c
- 配置选项:通过
CONFIG_ARM_UNALIGNED_ACCESS
控制是否允许非对齐访问 - 信号映射:
// 非对齐访问错误处理 static void __do_unaligned_access(struct pt_regs *regs, unsigned long addr) {if (user_mode(regs)) {// 发送SIGBUS信号force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr, current);return;}... }
4. ARMv7-M 架构的特殊处理
- 文件路径:
arch/arm/mach-cortexm/exception.c
- 关键函数:
hard_fault_handler()
、bus_fault_handler()
- 信号映射:
// Cortex-M的总线错误处理 void bus_fault_handler(struct pt_regs *regs) {// 通常通过系统调用向用户空间发送SIGBUSsend_sig(SIGBUS, current, 0);... }
总结
- 主要映射逻辑:
arch/arm/kernel/traps.c
和arch/arm/mm/fault.c
- 架构差异:ARMv7-M 与 ARMv7-A/R 的处理略有不同,具体取决于内核配置和硬件特性。