第3章 系统机制
Microsoft windows2000 提供了诸如执行程序、内核以及设备驱动程序等内核模式组件所使用的一些基本机制。本章将对以下系统机制进行解释并讲述他们的使用方法:
♦陷阱调度,包括中断、延迟过程调用(DCP)、异步过程调用(ACP)、异常调度和系统服务调度。
♦执行程序对象管理器。
♦同步,包括自旋锁、内核调度程序对象和等待的实现方式。
♦系统工作者线程
♦各种各样的机制如 Windows 2000 全局标记(global flag)。
♦本机过程调用(LPC)。
3.1 陷阱调度
中断和异常是操作系统使处理器转向正常控制流以外的编码情况。无论是硬件还是软件都能检测到。“陷阱”一词是指当异常或中断发生时,处理器捕捉正在执行的线程,并将控制转向操作系统固定位置的机制。在 Windows 2000 中,处理器将控制转向陷阱处理程序(trap handler),它是与特定中断或异常相关的函数。图3-1列出了一些激活陷阱处理程序的条件。
内核以下列方式区分中断和异常。中断是异步事件(可在任何时候发生),它与处理器正在执行什么无关。中断主要是由I/O设备、处理器时钟或定时器引发的,而且能被允许(开)或取消(关)。相反,异常是由于执行特定指令而引发的同步事件。在相同条件下,第二次运行相同数据的程序能重复异常。异常现象包括存储器存取违规、一定的调试程序指令和被0除错误。内核也把系统服务调用视为异常(尽管从技术上说他们是系统陷阱)。
无论硬件还是软件都回引起异常和中断。例如,总线错误异常时由硬件出故障引起的,而除0异常是由软件错误引起的。类似的,I/O设备也会产生中断,或者内核本身也能引起软中断(例如本章后文将要讲到的ACP或DCP)。
当产生硬件异常或中断时,处理器记录足够的机器状态以便返回控制流中的该点,而恢复执行,好像异常和中断没有发生一样。为达到这一目的,处理器在中断线程的内核栈中创建一陷阱帧(trap frame),并将线程的执行状态存储在中断线程内核栈中。陷阱帧通常是全部线程环境的子集(线程环境将在第6章介绍)。当线程调用与软中断相关的内核函数时,内核将软中断作为硬件处理的一部分进行处理或者同步处理。
大多数情况下,内核在将控制转给其他产生处理陷阱的现场的函数之前以及之后,都要安装前端陷阱处理函数,用以完成一般的陷阱处理任务。例如,如果是设备中断,内核硬件中断陷阱处理程序将控制转移给中断服务例程(ISR),它有设备驱动程序为中断设备提供。如果中断是由调用系统服务引起的,一般系统服务陷阱处理程序就将控制转移给正在执行中的特定系统服务函数。内核也为无法预测或无法处理的陷阱建立陷阱处理程序。这些陷阱处理程序通常执行系统函数KeBugCheckEx。只要内核检测到有问题或错误的行为,便停止计算机而如果不对其进行检查,将引起数据出错。(关于错误检查的进一步资料,参见4.5节“系统崩溃”)。以下几节将更详细的讲述中断、异常和系统服务调度。
3.1.1 中断调度
硬件引起的中断通常来自I/O设备,它们在需要服务时必须通知处理器。中断驱动设备允许操作系统通过中央处理器与I/O操作重叠而最大限度地使用处理器。线程启动从或到某一设备的I/O传输,在设备完成传输过程中执行有效工作。当该设备传输完成后,它就中断处理器请求服务。定点设备、打印机、键盘、磁盘驱动器和网卡一般都是中断驱动的。
系统软件也能产生中断。比如,内核能引起软中断,从而初始化线程调度并异步地中断线程的执行。为使处理器不被中断,内核也能禁止中断,但这是很少出现的--只有在临界点期间,如当它在处理某个中断或调度某一异常时。
内核安装了陷阱处理程序来响应设备中断。中断陷阱处理程序将将控制转移给处理中断的外部例程(ISR)或者转移给响应中断的内部内核例程。设备驱动程序将中断服务例程(ISR)提供服务设备中断,而内核 则为其他类型的中断提供中断处理例程。
在以下的章节中,你将会了解到硬件如何向处理器通知设备中断,内核所支持的中断类型、设备驱动程序与内核的交互的方式(作为中断处理的一部分),以及内核所能识别的软中断(加上用来实现这些的内核对象)。
1.硬件中断处理
在x86系统上,外部I/O中断进入到中断控制器的某条线中。接着控制器中断某条线上的处理器。一旦处理器被中断,它就查询控制器以获取中断请求(IRQ)。中断控制器再将IRQ翻译为一个中断号,用它作为中断调度表(IDT)结构的索引,并把控制转移给适当的中断调度例程。在系统启动时,Windows 2000 在IDT中填入处理中断和异常的内核例程的指针。
实验:查看IDT 利用在Kdex2x86.dll调试器扩展库中实现!idt命令,读者可以查看IDT的内容,包括有关Windows 2000 分配给中断(异常或IRQ)陷阱处理程序的信息。将0标记传递给!idt命令表示为硬件设备中断注册的设备驱动程序ISR。 下例说明了如何装载Kdex2x86.dll调试器扩展库以及!idt命令的输出结果: kd>.load dex2x86 Loaded dex2x86 extension DLL kd>!idt 0 00:80463440(ntkrnlmp!KiTrap00) 01:80463590(ntkrnlmp!KiTrap01) 02:0000144e 03:8046386c(ntkrnlmp!KiTrap03) 04:804639d4(ntkrnlmp!KiTrap04) 05:80463b18(ntkrnlmp!KiTrap05) 06:80463c78(ntkrnlmp!KiTrap06) 07:804641bc(ntkrnlmp!KiTrap07) 08:000014a8 09:80464558(ntkrnlmp!KiTrap09) 0a:80464660(ntkrnlmp!KiTrap0A) 0b:8046478c(ntkrnlmp!KiTrap0B) 0c:80464a90(ntkrnlmp!KiTrap0C) 0d:80464c9c(ntkrnlmp!KiTrap0D) 0e:80465708(ntkrnlmp!KiTrap0E) 0f:80465aac(ntkrnlmp!KiTrap0F) 10:80465bb4(ntkrnlmp!KiTrap10) 11:80465cd8(ntkrnlmp!KiTrap11) 12:80465aac(ntkrnlmp!KiTrap0F) 29:00000000 2a:804628fe(ntkrnlmp!KiGetTickCount) 2b:804629f0(ntkrnlmp!KiCallbackReturn) 2c:80462b10(ntkrnlmp!KiSetLowWaitHighThread) 2d:8046375c(ntkrnlmp!KiDebugService) 2e:80462420(ntkrnlmp!KiSystemService) 2f:80465aac(ntkrnlmp!KiTrap0F) 30:80461a50(ntkrnlmp!KiStartUnexpectedRange) 51:80461b9a(ntkrnlmp!KiUnexpectedInterrupt33) 52:813dbbe4(Vector:52,Irql:4,SyncIrql:5,Connected:TRUE,¬ No:0,ShareVector:FALSE,Mode:Latched,¬ ISR:i8042prt!I8042KeyboardInterruptService(f04b10cc)) 53:80461bae(ntkrnlmp!KiUnexpectedInterrupt35) 54:80461bb8(ntkrnlmp!KiUnexpectedInterrupt36) d0:80462090(ntkrnlmp!KiUnexpectedInterrupt160) d1:800638d4(halmps!HalpClockInterrupt) d2:804620a4(ntkrnlmp!KiUnexpectedInterrupt162) 例子中一些有趣的中断号在0x0到0x2a到0x2e的范围内,前面的范围包括x86异常中断(如页面错误是0xe异常,有KitTrap0E处理),后者则包括系统服务调度程序和其它被内核在内部作用从环境子系统到内核的快速入口点的软中断。在用来提供实验结果的系统上,时钟中断程序的中断号是0xd1,键盘设备驱动程序的键盘ISR的中断号是0x52。 |
明日待续。。。