始终可抢占且始终可中断

操作系统的可抢占性、可中断设计的目标是最大限度地提高系统性能。 任何线程都可以被优先级较高的线程抢占,并且任何驱动程序的中断服务例程 (ISR) 都可以被以更高的中断请求级别运行的例程中断 (IRQL) 。

内核组件根据以下优先级条件之一确定代码序列的运行时间:

  • 线程的内核定义的运行时优先级方案。

    系统中的每个线程都有关联的优先级属性。 通常,大多数线程具有 可变 优先级属性:它们始终是抢占的,并计划与当前处于同一优先级的所有其他线程一起运行轮循机制。 某些线程具有 实时 优先级属性:这些时间关键型线程将运行到完成,除非它们被具有更高实时优先级属性的线程抢占。 Microsoft Windows 体系结构不提供固有的实时系统。

    无论其优先级属性如何,在发生硬件中断和某些类型的软件中断时,系统中的任何线程都可以被抢占。

  • 内核定义的 中断请求级别 (IRQL) ,特定中断向量在给定平台上分配给该级别。

    内核确定硬件和软件中断的优先级,以便某些内核模式代码(包括大多数驱动程序)在更高的 IRQL 下运行,从而使其具有高于系统中其他线程的计划优先级。 执行内核模式驱动程序代码的特定 IRQL 由其基础设备 的硬件优先级 确定。

    内核模式代码始终是可中断的:具有较高 IRQL 值的中断随时可能发生,从而导致具有更高系统分配 IRQL 的另一段内核模式代码立即在该处理器上运行。 但是,当一段代码在给定 IRQL 中运行时,内核会屏蔽处理器上 IRQL 值较小或相等的所有中断向量。

最低 IRQL 级别称为 PASSIVE_LEVEL。 在此级别,不会屏蔽任何中断向量。 线程通常以 IRQL=PASSIVE_LEVEL 运行。 下一个更高的 IRQL 级别适用于软件中断。 这些级别包括APC_LEVEL、DISPATCH_LEVEL或内核调试WAKE_LEVEL。 设备中断的 IRQL 值仍然较高。 内核保留系统关键中断(例如来自系统时钟或总线错误)的最高 IRQL 值。

某些系统支持例程在 IRQL=PASSIVE_LEVEL 运行,因为它们作为可分页代码实现或访问可分页数据,或者因为某些内核模式组件设置了自己的线程。

同样,某些 标准驱动程序例程 通常以 IRQL=PASSIVE_LEVEL 运行。 但是,多个标准驱动程序例程在 IRQL=DISPATCH_LEVEL 运行,或者对于最低级别的驱动程序,运行在设备 IRQL (也称为 DIRQL) 。 有关 IRQL 的详细信息,请参阅 管理硬件优先级

驱动程序中的每个例程都是可中断的。 这包括以高于 PASSIVE_LEVEL 的 IRQL 运行的任何例程。 仅在运行某个特定 IRQL 时未发生更高 IRQL 中断的情况下,在特定 IRQL 上运行的任何例程才保留对处理器的控制。

与某些旧版个人计算机操作系统中的驱动程序不同,Microsoft Windows 驱动程序的 ISR 从来不是执行驱动程序的大部分 I/O 处理的大型复杂例程。 这是因为任何驱动程序的 中断服务例程 (ISR) 都可以被另一个例程 (中断,例如,另一个驱动程序的 ISR) 在更高的 IRQL 上运行。 因此,驱动程序的 ISR 不一定保持对 CPU 的控制,从执行路径的开始到结束,不间断。

在 Windows 驱动程序中,ISR 通常会保存硬件状态信息,将 延迟过程调用 (DPC) 排队,然后快速退出。 稍后,系统会取消对驱动程序的 DPC 排队,以便驱动程序可以在较低的 IRQL (DISPATCH_LEVEL) 完成 I/O 操作。 为了获得良好的整体系统性能,以高 IRQL 运行的所有例程都必须快速放弃对 CPU 的控制。

在 Windows 中,所有线程都具有线程上下文。 此上下文包含标识拥有线程的进程的信息以及其他特征,例如线程的访问权限。

通常,在请求驱动程序的当前 I/O 操作的线程上下文中,仅调用最高级别驱动程序。 中间级别或最低级别驱动程序永远不能假定它在请求其当前 I/O 操作的线程的上下文中执行。

因此,驱动程序例程通常在 任意线程上下文中执行 -- 调用标准驱动程序例程时,任何线程的上下文都是最新的。 出于性能原因, (避免) 上下文切换,很少有驱动程序设置自己的线程。