Linux 驱动开发之中断分析2(基于Linux6.6)---中断处理流程介绍
一、概述
下面由一张流程图来看一下当中断发生时的处理流程:

1. 中断信号触发
中断由硬件设备或外部事件触发。常见的触发来源包括:
- 硬件中断:如外部设备(网卡、硬盘、USB 设备、键盘等)产生的中断。
- 定时器中断:系统时钟产生的周期性中断,通常用于调度进程。
- 软件中断:由软件发起的中断,例如系统调用。
2. 硬件中断的响应
当硬件设备发出中断信号时,CPU 会立即响应这个信号,暂停当前执行的任务并转向中断处理程序。此时,硬件会根据中断的优先级确定是否允许当前中断执行。
中断的响应过程如下:
- 中断信号到达:硬件设备触发中断请求(IRQ)。
- CPU 停止当前任务:当前正在执行的指令会被暂停,CPU 会保存现场(如寄存器的状态),以便中断处理完成后可以恢复执行。
- 进入中断处理模式:CPU 切换到内核模式,开始执行中断服务程序(ISR,Interrupt Service Routine)。
3. 中断向量表查找
Linux 内核通过中断向量表来管理不同的中断类型。每个中断源都对应一个中断号(IRQ)。当 CPU 收到中断信号时,它会根据中断号查找中断向量表,定位到对应的中断处理函数。
- 中断向量表通常包含了每个中断类型对应的处理函数地址。Linux 内核会根据中断号(或中断向量)查找到正确的 ISR 地址。
4. 中断服务程序 (ISR) 执行
当 CPU 找到对应的中断处理程序(ISR)后,会执行该程序。ISR 的作用是完成最低限度的中断处理,通常是完成硬件设备的状态检查、清除中断源等。
- 处理中断源:ISR 会根据中断类型检查并处理硬件设备的状态。例如,在网络中断中,ISR 会检查网络设备的接收缓冲区并读取数据包。
- 最小化中断处理时间:ISR 需要尽可能快地执行,以便不阻塞其他重要的中断请求。通常,ISR 只完成硬件操作的处理,不会进行复杂的计算或任务调度。
ISR 结束后,内核会通知硬件中断已经处理完成,可以重新开始接收后续的中断信号。
5. 软中断 (Softirq) 或工作队列 (Workqueue)
为了避免 ISR 过长,Linux 内核将一些需要进一步处理的工作推迟到软中断(Softirq)或工作队列中。软中断通常用于高优先级的任务,而工作队列用于较低优先级的异步处理。
- 软中断:软中断是内核的一种机制,用于在中断处理程序完成后执行一些重要的延迟处理任务,如网络协议栈处理或数据包传输的进一步处理。软中断由内核自动调度,通常会在中断返回后进行执行。
- 工作队列:工作队列用于推迟处理复杂的任务,例如磁盘操作或文件系统处理。工作队列中的任务会在稍后的时间内执行,通常会在系统处于空闲状态时被调度。
6. 中断结束与恢复上下文
中断处理程序(ISR)完成后,CPU 会恢复到被中断之前的状态,并继续执行被暂停的任务。
- 恢复现场:ISR 执行完毕后,CPU 恢复上下文。现场保存了在中断发生前寄存器的状态,包括程序计数器(PC)、堆栈指针(SP)等。通过恢复现场,系统可以无缝地返回到被中断的进程或任务。
- 中断标志清除:ISR 会清除中断标志位,告知硬件中断已经处理完成,硬件可以继续发出中断请求。
7. 调度与任务切换(如果需要)
中断处理程序结束后,内核可能会触发任务调度,判断是否需要切换当前执行的进程。调度器会检查是否有更高优先级的任务需要执行,或者当前进程的时间片是否已用完。
- 时间片轮转:如果定时器中断触发(例如时钟中断),内核会检查当前进程的时间片是否用完,若用完则触发进程调度,可能会进行进程切换。
- 上下文切换:如果需要切换任务,内核会保存当前任务的状态,并加载新任务的状态,完成上下文切换。
二、 中断硬件框架
中断的主动通知特性需要硬件设施支持。在数字逻辑电路层面,外部设备和处理器之间有一条专门的中断信号线(Interrupt Line),用于连接外设与CPU的中断引脚(Interrupt Pin)。当外部设备发生状态改变时,可以通过这条信号线向处理器发出一个中断请求(Interrupt Request,IRQ),其中外部设备通常被称作中断源(Interrupt Source)。
处理器一般只有两根左右的中断引脚(Cortex A9 中的 IRQ、FIQ),而管理的外设却很多。为了解决这个问题,现代设备的中断信号线并不是与处理器直接相连,而是与一个称为中断控制器的设备相连接,后者才跟处理器的中断引脚连接。中断控制器一般可以通过处理器进行编程配置,在Cortex A9 中称为通用中断控制器GIC(Gerneric Interrupt Controller)。
下面是一个简化的框架图和对其各个组成部分的说明:
+--------------------+ +---------------------+ +-------------------+
| Hardware Device | | Interrupt | | CPU |
| |---->| Controller |---->| |
| (e.g., Network, | | (e.g., PIC, APIC, | | (Interrupt |
| Disk, Timer) | | I/O APIC) | | Handler) |
+--------------------+ +---------------------+ +-------------------+
| |
| |
v v
+---------------------+ +-------------------+
| Interrupt | | Interrupt |
| Vector Table |---->| Service Routine |
| (ISR Handlers) | | (ISR) |
+---------------------+ +-------------------+
| |
v |
+------------------------+ |
| SoftIRQ / Workqueue |<----------+
+------------------------+
|
v
+---------------------+
| Scheduler |
+---------------------+
各个组件的作用:
-
硬件设备 (Hardware Device):
- 这些设备会触发中断。例如,网络适配器、硬盘驱动器、定时器等硬件设备会在数据可用或其他事件发生时产生中断请求。
- 每个硬件设备都有一个唯一的中断请求线(IRQ),用于向 CPU 发出中断信号。
-
中断控制器 (Interrupt Controller):
- 中断控制器(例如,8259 PIC、APIC)负责接收硬件设备的中断请求(IRQ)并将其传递给 CPU。它根据中断优先级进行排序,并决定是否允许 CPU 响应该中断。
- 现代系统常使用 APIC(高级可编程中断控制器)来处理更复杂的中断管理。
-
CPU (Central Processing Unit):
- CPU 是处理中断信号的核心部分。当 CPU 接收到中断信号时,它会暂停当前任务,保存现场(如寄存器状态),并根据中断向量表跳转到相应的中断处理程序(ISR)。
- 在处理中断时,CPU 会切换到内核模式,并执行与中断源相关的处理工作。
-
中断向量表 (Interrupt Vector Table):
- 中断向量表包含了所有中断类型的中断处理程序地址(ISR)。每个中断源(硬件中断、定时器中断等)都有一个对应的中断号,CPU 根据这个中断号查找到相应的中断服务程序的地址。
-
中断服务例程 (ISR - Interrupt Service Routine):
- ISR 是处理硬件中断的实际函数。ISR 主要负责对中断源的最基本处理,如读取设备数据、清除中断标志等。
- ISR 执行时会尽量减少阻塞时间,以避免延迟其他重要的中断请求。
-
软中断 (SoftIRQ) 和工作队列 (Workqueue):
- 软中断和工作队列机制用于推迟中断处理后的复杂任务。由于 ISR 需要尽可能快地执行,因此一些复杂的任务会被推迟到软中断(SoftIRQ)或工作队列(Workqueue)中进行处理。
- 软中断用于高优先级的任务,例如网络协议栈处理,工作队列用于较低优先级的异步处理,如磁盘操作或文件系统的处理。
-
调度器 (Scheduler):
- 中断处理完成后,调度器会检查当前是否需要切换进程。如果中断触发了某个需要调度的任务(例如时间片用尽,或者有更高优先级的进程需要执行),调度器会执行进程切换(上下文切换),确保系统资源得到合理分配。
中断处理流程概述:
- 硬件触发中断:硬件设备触发中断信号,通过中断控制器传递给 CPU。
- 中断控制器接收中断请求:中断控制器对多个中断信号进行排序,选择一个中断处理。
- CPU 响应中断:CPU 停止当前进程,保存当前执行状态并跳转到中断处理程序。
- 执行中断服务例程 (ISR):执行简单的硬件中断处理,如读取数据、清除中断标志。
- 软中断或工作队列:将更复杂的任务推迟到软中断或工作队列中进行处理。
- 任务调度:完成中断处理后,调度器可能会检查是否需要调度新进程。
通过这一框架,Linux 内核能够高效地管理硬件中断和系统任务调度,保证系统对外部事件的响应和资源的高效分配。
三、 中断向量表
中断向量表其实是处理器内部的概念,因为处理器除了会被外部设备中断外,其内部也可能产生异常等事件,例如在MIPS中,中断只是异常的一种。当这些事件发生时,CPU必须暂停手头上的工作,转而去处理中断或异常,因此处理器需要知道到哪里去获得这些中断或异常的处理函数的目标地址。中断向量表就是用来解决这个问题,其中每一项都是一个中断或异常处理函数的入口地址,具体来说4个字节的函数指针将指向一段汇编微码(intConnectCode)执行跳转。
外部设备的中断常常对应向量表中的某一项,这是通用框架的外部中断处理函数入口,因此在进入通用的中断处理函数之后,系统必须知道正在处理的中断是哪一个设备产生的,而这正是由软件中断号irq定的决。中断向量表的内容是由操作系统在初始化阶段来填写,对于外部中断,操作系统负责实现一个通用的外部中断处理函数,然后把这个函数的入口地址放到中断向量表中的对应位置。用户注册设备驱动ISR,实际上就是挂接到中断向量表中,覆盖某一项的默认处理实现特化。
1. 中断向量表概述
中断向量表通常是一个固定位置的内存区域,包含了不同中断号对应的中断服务例程的入口地址。每当一个硬件或软件中断发生时,CPU 会根据中断号查找这个表,并跳转到相应的中断处理程序。
中断向量表的结构通常与硬件平台的架构密切相关。对于 x86 架构、ARM 架构等不同平台,它们有不同的中断向量表实现。
2. 中断向量表结构
中断向量表的每个条目对应一个中断号。当中断发生时,CPU 使用中断号来查找中断向量表,并跳转到相应的中断服务程序(ISR)。在 Linux 中,硬件中断通常使用一个固定的中断向量表条目,软件中断(如系统调用)也有相应的条目。
在早期的 x86 架构上,通常会有 256 个条目(对于不同的中断类型和优先级),每个条目指向一个中断处理程序的入口地址。
3. Linux 中断向量表的组织
Linux 内核使用一组中断处理程序来响应硬件和软件中断。对于大多数硬件平台,Linux 将中断向量表分为几个部分,分别处理不同类型的中断。
-
硬件中断:
- 硬件中断通过中断控制器(如 x86 系统的 PIC 或 APIC)生成,每个硬件设备都会有一个对应的中断号(IRQ)。
- 这些硬件中断会通过中断向量表找到对应的 ISR。硬件中断通常会直接执行对应的 ISR(例如处理网卡、磁盘驱动等的中断)。
-
系统调用:
- 系统调用通常也会通过中断来实现。Linux 使用
int 0x80(在 x86 上)或syscall指令(在 x86_64 上)来触发系统调用中断。
- 系统调用通常也会通过中断来实现。Linux 使用
-
软中断(SoftIRQ)和任务队列(Tasklets):
- 软中断和任务队列在中断上下文外部执行。它们被用于延迟中断处理,允许 CPU 在处理中断时不会被阻塞。
4. x86 架构的中断向量表
在 x86 架构上,Linux 中的中断向量表通常由 256 个条目组成,每个条目指向一个中断服务例程。前几个中断向量由 BIOS 和操作系统保留用于处理硬件和异常中断。以下是一些常见的中断向量:
- 0x00 – 0x1F:用于 CPU 异常和硬件中断(例如:除零错误、页面错误、调试中断等)。
- 0x20 – 0x2F:用于外部硬件中断,通常由可编程中断控制器(PIC)或高级可编程中断控制器(APIC)生成。
- 0x80:用于系统调用。在 Linux 中,系统调用通过这个中断向量触发,通常会跳转到内核的系统调用处理函数。
- 0xFF:软件中断,一些调试或特定的内核操作可能使用这个中断。
5. Linux 内核如何配置中断向量表
在 Linux 内核中,中断向量表的配置是由特定的硬件架构代码负责的。例如,在 x86 架构中,Linux 内核会初始化 IDT(Interrupt Descriptor Table,中断描述符表),这个表格保存了中断向量及其对应的 ISR 地址。
-
IDT(Interrupt Descriptor Table):这是中断向量表在 x86 架构上的实现。IDT 是一张映射表,映射中断号到对应的中断处理程序。
在 Linux 中,IDT 通常由
arch/x86/kernel/entry_32.S(32 位系统)或arch/x86/kernel/entry_64.S(64 位系统)中的汇编代码进行设置。通过 IDT,CPU 能够找到对应的中断服务程序的入口地址。
6. 硬件中断和软件中断的区别
-
硬件中断:
- 由外部设备触发,如网卡、磁盘、定时器等硬件设备发出信号,告诉 CPU 它们有数据或事件需要处理。
- 在 Linux 中,硬件中断通常通过外部中断控制器(如 APIC 或 PIC)来传递给 CPU。
-
软件中断:
- 由程序或内核产生的中断,通常用于请求操作系统的服务(例如,系统调用)。
- 在 x86 系统中,软件中断(如
int 0x80或syscall)用于从用户空间请求进入内核空间执行特权操作。
四、中断流程分析
Linux 的中断处理流程大致可以分为以下几个步骤:
1.硬件中断触发
当硬件设备需要 CPU 处理时,设备会发出中断信号。硬件中断信号首先会被外部中断控制器(如 x86 架构的 PIC 或 APIC)接收,并传递给 CPU。此时,CPU 会暂停当前执行的任务,开始处理中断。
2.CPU 进入内核模式
当 CPU 收到中断信号时,它会切换到内核模式,并开始处理中断。此时,CPU 会保存当前上下文(如程序计数器、寄存器等),并跳转到中断服务例程(ISR)进行处理。
3.查找中断向量
CPU 会根据中断号查找中断向量表,找到相应的中断服务例程。中断向量表是一个由操作系统维护的数据结构,其中包含了不同中断号对应的处理程序地址。Linux 内核使用 IDT(Interrupt Descriptor Table,中断描述符表)来维护这些信息。
4.中断服务例程(ISR)执行
一旦找到对应的 ISR,CPU 就会跳转到中断服务例程执行。在 ISR 中,操作系统会根据中断的类型执行相应的操作,例如读取硬件设备的数据、清除中断标志等。中断服务例程应该尽可能快速执行,以便尽早恢复正常任务。
5.处理软中断和工作队列
有些中断需要更复杂的处理,但为了避免在 ISR 中做过多的工作,Linux 将这些任务推迟到软中断或工作队列(Tasklet)中。在硬中断处理完成后,系统会通过软中断或工作队列机制延迟执行更复杂的操作,这样可以防止中断处理占用过多的 CPU 时间。
6.恢复上下文并返回用户空间
在 ISR 执行完毕后,CPU 会恢复被中断前的上下文。此时,中断处理的上下文(如寄存器状态)会被恢复,CPU 会返回到中断发生前的执行流。如果中断发生在内核模式下,CPU 会继续执行内核中的其他任务;如果发生在用户模式下,CPU 会返回用户空间继续执行。
+-------------------+
| 外部中断触发 |<----------------------+
| (硬件设备发出) | |
+-------------------+ |
| |
v |
+--------------------+ |
| 中断控制器接收中断 | |
| (如APIC、PIC) | |
+--------------------+ |
| |
v |
+--------------------+ |
| CPU 处理中断 |<----------------------+
| (跳转到内核模式)|
+--------------------+
|
v
+--------------------+ 查找 IDT
| 中断服务例程 (ISR) |----------------------------+
| (硬件设备处理) | |
+--------------------+ |
| |
v |
+--------------------+ |
| 完成硬件中断处理 | |
| (处理I/O或清除中断) |<------------------------+
+--------------------+ |
| |
v |
+--------------------+ |
| 延迟处理任务(软中断/ | |
| 工作队列) |----------------------------+
+--------------------+ |
| |
v |
+--------------------+ |
| 恢复进程上下文 | |
| (中断返回前的状态) |<------------------------+
+--------------------+
|
v
+--------------------+
| 返回用户态/内核态 |
+--------------------+
894

被折叠的 条评论
为什么被折叠?



