在 Linux 内核中,中断返回(Interrupt Return) 是指处理器从中断处理程序(Interrupt Handler)或异常处理程序中退出,并恢复到被中断前的用户态或内核态继续执行的过程。
这个过程涉及硬件状态保存与恢复、内核栈切换以及上下文切换等复杂机制,以下是 Linux 中断返回的详细流程解析:
中断返回的基本概念
当 CPU 响应一个中断时,会:
- 保存当前上下文(如寄存器、程序计数器 PC、状态寄存器 CPSR/PSR 等)。
- 跳转到对应的中断向量表入口。
- 执行中断处理程序(ISR, Interrupt Service Routine)。
- 执行中断返回指令(如
eret、iret、sret等,取决于架构)。 - 恢复之前保存的上下文,继续执行被中断的代码。
中断返回的关键步骤(以 ARM64 为例)
中断入口保存上下文
当中断发生时,硬件自动保存部分寄存器到异常栈(EL1/EL0 栈),包括:
SPSR_EL1(保存原 CPSR)ELR_EL1(保存返回地址,即被中断的指令地址)
执行中断处理程序
内核中的中断处理程序通常由 C 代码编写,
static irqreturn_t my_irq_handler(int irq, void dev_id) { // 处理中断逻辑 return IRQ_HANDLED; }
该函数通过 request_irq() 注册到内核中断子系统。
中断返回指令
在中断处理程序结束后,内核会执行架构特定的中断返回指令:
- ARM64:
eret(Exception Return) - x86:
iretq(64 位中断返回) - ARM32:
srsfd/ldmfd+subs pc, lr, #4等
这些指令会从 SPSR 和 ELR 中恢复状态寄存器和程序计数器,从而返回到被中断的代码位置。
中断返回的详细流程(ARM64 示例)
异常向量表入口
在 arch/arm64/kernel/entry.S 中定义了异常向量表:
ENTRY(vectors)
kernel_ventry 1, sync_invalid // Synchronous
kernel_ventry 1, irq_invalid // IRQ
kernel_ventry 1, fiq_invalid // FIQ
kernel_ventry 1, error_invalid // Error
当中断发生时,CPU 跳转到 irq_entry 或类似标签。
保存上下文
el1_irq:
save_user_regs 
// 保存用户态寄存器
enable_dbg // 启用调试
kasan_disable_current // 禁用 KASAN
mov x0, sp // 传递栈指针
bl do_el1_irq // 调用 C 层中断处理
restore_user_regs 0 // 恢复用户态寄存器并返回
调用 C 层中断处理
asmlinkage void __exception_irq_entry do_el1_irq(struct pt_regs regs)
{
handle_IRQ(arch_irq_to_hwirq(regs->regs[0]), regs);
}
中断返回
restore_user_regs:
restore_kernel_sp // 恢复内核栈
msr spsr_el1, x0 // 恢复状态寄存器
msr elr_el1, x1 // 恢复返回地址
eret // 异常返回指令
eret 指令会从 SPSR_EL1 恢复 CPSR,从 ELR_EL1 恢复 PC,从而返回到被中断的代码位置。
中断返回的注意事项
中断嵌套与禁用
- 在中断处理程序中,可以通过
local_irq_disable()禁用本地中断,防止嵌套。 - 中断返回前,通常会重新启用中断(
local_irq_enable()),除非显式禁用。
软中断与 BH(Bottom Half)
- 硬中断处理程序应尽量简短,耗时操作交给软中断(softirq)或 tasklet。
- 中断返回后,内核会检查是否有待处理的软中断或 BH,并执行它们。
上下文一致性
- 中断返回时,必须确保所有寄存器、栈指针、状态寄存器都已正确恢复,否则会导致系统崩溃。
异常与中断的区别
- 异常(Exception):由 CPU 内部事件触发(如除零、页错误)。
- 中断(Interrupt):由外部设备触发(如定时器、网卡)。
- 两者在中断返回机制上类似,但入口点和处理方式略有不同。
Linux 中断返回是一个涉及硬件和内核协同工作的复杂过程,主要包括:
- 保存上下文:硬件和内核保存当前状态。
- 执行中断处理程序:C 代码处理中断逻辑。
- 恢复上下文:从保存的状态中恢复寄存器、栈指针、PC 等。
- 执行中断返回指令:如
eret、iret等,返回到被中断的代码位置。
理解中断返回机制对于调试内核崩溃、优化中断性能、编写驱动程序至关重要。
首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/484280.html



