tgjarwl的博客

道可道,非常道;名可名,非常名

记录生活,记录更好的自己。


陷阱分发(Trap Dispatching)

前言

身为攻城狮,还是回归技术本身吧。最近再重温Windows Internals。很喜欢这本书的作者叙述windows的逻辑顺序,先总结下里面的第一个机制吧,Trap。

陷阱分发(Trap Dispatching)

借用书中的一句原话

中断和异常是导致处理器转向正常控制流之外的两种操作系统条件。

而 Trap 就是当这两种事件发生时,提供的统一处理的机制(其实就是概念上的统一)。

windows有一个特点,就是喜欢把几种相似的情况,给统一一下,然后提供一个新的名词出来。那windows是如何把这两种情况给统一起来的?看下面的一张图 avatar

从图片中可以看到,中断对应的处理程序为ISR,系统服务对应的其实就是SSDT,异常对应的则是异常分发。然而windows把这些事件的处理程序统用一个统一的称呼来表示,那就是 陷阱处理器(Trap Handlers),再细说中断和异常前,windows是如何把他们统一起来的。

中断分发表 (IDT)

这个用来统一这一概念的结构,就是IDT(CPU架构的原因,不用也没有办法),IDT最多可以容纳256个表项,windows把这些事件分布在了IDT中的不同的区域,下图是windows internals中的一张图 avatar

从上往下叙述的话,

0x00-0x13       第一部分(前20项),是cpu指令执行过程中的一些异常处理程序。
0x2A            KiGetTickCount
0x2B            KiCallbaclReturn
0x2C            KiRaiseAssertion
0x2D            KiDebugService
0x2E            KiSystemService
0x30-0xFF       剩下的这部分留给了硬件和用户使用。

从最顶层看的话,IDT完美的把系统内核和r3隔离开来,又提供了统一的机制来进行交互。我们知道中断是有级别的,等级越高的中断,会屏蔽等级较低的中断,单纯的划分出来几部分,是远远不够的,还需要提供额外的一个机制去划分这些异常跟中断的等级,避免不合理的抢占。同时要兼顾硬件跟软件的完美统一。于是微软就相出了一个绝佳的方案,IRQL。

中断请求级别 (IRQL)

先来谈下,硬件中断控制器,早期的x86时代,从书本上也应该了解过,中断是依赖i8259A可编程中断控制器(简称PIC),后来又出现了一个更高级的i82489高级可编程中断控制器(简称APIC)。APIC通过可编程的方式,让系统提可以相应中断发生与控制中断。但是微软却禁用了APIC的绝大部分功能,采用手动控制的方式(禁用了APIC自己的中断转送算法等一些内置的功能,自己在软件层去实现控制)。把硬件的中断,映射到了IDT 0x30开始的部分区域。并为提供了一个软件方式的中断控制器(在HAL层)。同时又提供了一个软件层面的中断请求级别,也就是IRQL。来统一管理硬件和软件中断。

avatar

这样当一个异常或者中断发生后,系统通过提升IRQL, 例如:缺页异常(int 0e),当cpu执行到对应的ISR后,会通过提升IRQL等级(KeRaiseIrql),来屏蔽低等级的中断,待处理完成后。继续之前的执行。

尽管中断(中断时调用ISR),异常(异常发生后,走异常分发逻辑)的处理逻辑是不一样,那也只是具体到个例后实现的问题。

FAQ

其实到这里,好多问题其实就可以很方便的理解了,例如:

IRQ和IRQL之间是什么关系? 中断的每一个中断都是有中断号的。而windows通过变成的方式,把IRQ给映射到了IDT中0x30开始的位置,同时在处理函数中,指定了一个IRQL。因为这个IRQL是windows自己指定的,所以一方面可以说是线性关系(按IRQ的顺序指定的IRQL),但是从另一方面说,因为这个IRQ是windows自己执行的,所以也可以说没有关系。

在明白了windows是如何组织架构这个东西后,所有的东西都是会很方便的理解和记忆了。