1. 中断基础概念:中断向量、中断号、中断上下文、中断处理流程
中断是硬件与软件交互的核心机制,也是 Linux 驱动响应外部事件的最高效途径。理解中断的底层概念,是后续进行中断与 tasklet 性能调优的基石。本节将系统梳理中断向量、中断号、中断上下文以及完整的中断处理流程。
1.1 中断向量与中断号
中断向量和中断号是中断系统的两个关键标识,但它们在硬件和软件层面有不同的含义。
| 概念 | 定义 | 作用域 | 典型范围 |
|---|---|---|---|
| 中断向量 | CPU 架构定义的、指向中断服务程序(ISR)入口地址的索引或指针 | 硬件/CPU 架构层 | 0~255(x86 实模式) |
| 中断号(IRQ) | Linux 内核为每个中断源分配的软件抽象编号 | 操作系统/驱动层 | 0~NR_IRQS-1(通常 0~15 为传统 IRQ) |
关键区别:中断向量由 CPU 厂商定义,用于硬件查找 ISR;中断号由内核管理,用于驱动注册和中断路由。在 x86 架构中,中断向量 0x20~0x2F 通常映射到 IRQ 0~15。
调优提示:在 /proc/interrupts 中看到的编号是中断号(IRQ),而非中断向量。驱动开发中只需关注中断号,中断向量由内核和硬件自动处理。
1.2 中断上下文
中断上下文是 Linux 内核中一个特殊的执行环境,与进程上下文有本质区别。
- 进程上下文:可以睡眠、可以调度、可以访问用户空间、持有锁时可以阻塞。
- 中断上下文:不可睡眠、不可调度、不可访问用户空间、持有锁时必须使用 spinlock。
| 特性 | 进程上下文 | 中断上下文 |
|---|---|---|
| 可睡眠 | 是 | 否 |
| 可调度 | 是 | 否 |
| 访问用户空间 | 是 | 否 |
| 锁类型 | mutex/semaphore | spinlock |
| 当前进程指针 | 有效 | 无效(指向被中断进程) |
常见错误:在中断上下文中调用 kmalloc(GFP_KERNEL) 或 mutex_lock() 会导致内核崩溃。必须使用 GFP_ATOMIC 和 spin_lock()。
1.3 中断处理流程
从硬件触发中断到驱动 ISR 执行完毕,整个流程分为硬件阶段和软件阶段。
核心原则:中断处理必须快——上半部(Top Half)只做最紧急的硬件操作,耗时工作推迟到下半部(Bottom Half)如 tasklet、workqueue 中完成。
1.3.1 完整中断处理流程步骤
- 硬件触发:外设通过中断线向中断控制器(如 APIC、GIC)发送电平或边沿信号。
- 中断控制器仲裁:中断控制器根据优先级选择最高优先级中断,向 CPU 发送中断请求。
- CPU 响应:CPU 保存当前上下文(寄存器、程序计数器),查找中断向量表,跳转到通用中断入口。
- 内核通用入口:保存所有寄存器,调用
handle_irq()或do_IRQ(),根据中断号查找已注册的 IRQ 描述符。 - 调用驱动 ISR:内核调用驱动注册的
request_irq()回调函数(上半部)。 - 上半部执行:驱动 ISR 执行硬件操作(如读取状态寄存器、清除中断标志),返回
IRQ_HANDLED或IRQ_WAKE_THREAD。 - 下半部调度:如果 ISR 返回
IRQ_WAKE_THREAD,内核调度 threaded IRQ;如果使用 tasklet,则在软中断上下文中执行。 - 恢复现场:CPU 恢复寄存器,返回被中断的进程继续执行。
1.3.2 中断处理流程 SVG 架构图
1.4 中断处理流程中的关键数据结构
内核使用 irq_desc 结构体管理每个中断号的状态、处理函数和标志位。
// include/linux/irqdesc.h (简化)
struct irq_desc {
struct irq_data irq_data; // 硬件相关数据
unsigned int __percpu *kstat_irqs; // 中断统计
irq_flow_handler_t handle_irq; // 中断流处理函数
struct irqaction *action; // 驱动注册的 action 链表
unsigned int status_use_accessors; // 状态标志
const char *name; // 中断名称
struct proc_dir_entry *dir; // /proc/irq 目录
};
调优切入点:通过 /proc/interrupts 观察每个 CPU 上的中断分布,可以判断是否存在中断负载不均。后续章节将介绍如何使用 irqbalance 和 smp_affinity 进行调优。
1.5 中断处理流程总结
| 阶段 | 执行者 | 耗时要求 | 可调度 | 典型操作 |
|---|---|---|---|---|
| 硬件触发 | 外设 + 中断控制器 | 纳秒级 | 否 | 信号传输、优先级仲裁 |
| CPU 响应 | CPU 硬件 | 纳秒级 | 否 | 保存上下文、查向量表 |
| 内核通用入口 | 内核代码 | 微秒级 | 否 | 查找 irq_desc、调用 handle_irq |
| 驱动 ISR 上半部 | 驱动代码 | 微秒级(必须短) | 否 | 读状态寄存器、清中断标志 |
| 下半部调度 | 内核软中断/tasklet | 毫秒级 | 否(软中断) | 数据拷贝、协议处理 |
| 恢复现场 | CPU 硬件 | 纳秒级 | 否 | 恢复寄存器、返回进程 |