Windows 中断机制与线程调度详解
1. 中断请求(IRQ)与可编程中断控制器(PIC)
中断是计算机响应硬件或软件事件的一种机制。在 x86 架构中,中断分为两类:
- 内部中断:由 CPU 内部事件触发,例如执行
int指令或发生除零错误。 - 外部中断:由硬件设备通过中断控制器(如 PIC 或 APIC)向 CPU 发送信号触发,包括不可屏蔽中断(NMI)和可屏蔽中断(INTR)。
现代系统使用高级可编程中断控制器(APIC)来管理中断,APIC 通过 INTR 引脚向 CPU 发送中断请求。
IRQ 与优先级
传统 PIC 支持 16 个 IRQ,而 APIC 将 IRQ 的数量扩展到了 24 个。每个 IRQ 都有各自的优先级别。正在运行的线程随时可以被中断打断,进入中断处理程序。当优先级更高的中断来临时,即使当前正在执行优先级较低的中断处理程序,也会被打断,转而去执行更高级别的中断处理函数。
2. 中断请求级(IRQL)
Windows 在硬件中断的基础上,提出了中断请求级(IRQL) 的概念,将中断优先级抽象为 32 个级别(0~31),数字越大,优先级越高。
- 0~2 级:软件中断,用于线程调度、异步过程调用(APC)等。
- 3~31 级:硬件中断,涵盖了 APIC 中的 24 个 IRQ 以及一些系统内部使用的级别。
下图展示了32位Windows中的IRQL:

在64位Windows中,IRQL变为了16个:

DIRQL(设备中断请求级)
Windows 将 24 个硬件 IRQ 映射到了从 DISPATCH_LEVEL 到 PROFILE_LEVEL 之间的 IRQL 级别。不同硬件的中断处理程序运行在不同的 IRQL 级别上,这个级别被称为设备中断请求级(DIRQL)。
- Windows 大部分时间运行在软件中断级别(如
PASSIVE_LEVEL或APC_LEVEL)。 - 当设备中断来临时,操作系统会将当前处理器的 IRQL 提升至该设备对应的 DIRQL 级别,并执行中断处理函数(ISR)。
- 中断处理完成后,操作系统再将 IRQL 恢复到原来的级别。
下面说说比较重要的IRQL。
Passive
这是最低中断请求级别。在这个级别下,CPU可以响应所有的中断,并且可以执行所有内核操作,用户模式线程和大部分内核驱动入口点都是在这个级别中的。
Disaptch
内核调度器工作于这个IRQL。所以在这个大于等于级别上,不可以执行任何等待(互斥量、信号量、事件等),因为调度器无法在这样的级别中工作。并且在这个级别上,无法处理任何页错误。
3. 线程调度与线程优先级
线程优先级和 IRQL 是两个容易混淆的概念,需要明确区分:
- IRQL:是 CPU 级别的概念,用于屏蔽或允许特定类型的中断。所有用户应用程序都运行在
PASSIVE_LEVEL级别,这是最低的 IRQL,因此可以被任何其他 IRQL 级别的程序(如中断处理程序)打断。 - 线程优先级:是操作系统调度器使用的概念,用于决定在众多就绪线程中,哪个线程能获得 CPU 时间片。线程优先级只在程序运行于
PASSIVE_LEVEL级别时才有意义。
调度过程
负责调度线程的内核组件(调度器)运行在 DISPATCH_LEVEL 级别的 IRQL 上。当 IRQL 提升到 DISPATCH_LEVEL 时,所有应用程序线程的执行都会被暂停,等待调度器根据优先级算法重新选择下一个要运行的线程。
4. I/O 请求与中断处理上下文
当应用程序调用 ReadFile 等 I/O 函数时,内核会创建一个 I/O 请求包(IRP),例如 IRP_MJ_READ。这个 IRP 随后被传递到对应设备驱动程序的派遣函数中。
关键点:派遣函数运行在调用 ReadFile 的线程上下文中,也就是说,ReadFile 和驱动程序的派遣函数位于同一个线程上下文中。
中断服务例程(ISR)的执行
当一个硬件中断来临时,中断服务例程(ISR)是由最初被中断的线程执行的。Windows 没有为中断处理创建特殊的线程,ISR 由当时在被中断的处理器上运行的任意线程来执行。
重要特性:线程执行 ISR 所花费的时间,不计入该线程的时间片。这意味着,即使一个线程频繁地被中断并执行 ISR,也不会因此减少它运行用户代码的时间配额。

2403

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



