当以艺术眼光看程序,寻找程序后面的原理,做到化而不忘
全部博文(57)
分类: Windows平台
2014-06-07 16:02:56
其实软中断就是DISPATCH_LEVEL, APC_LEVEL, PASSIVE_LEVEL这三个中断级别,这里要注意一下,这里的中断不是硬件意义上的中断,比如时钟中断,而是软件中断,软件模拟出来的中断。问题来了:为什么要用软中断?我是这样理解的,因为Windows在响应外界的硬件中断,时间一定要足够短,否则一切事都放在中断做,那Windows会慢死了,所以它将中断分为两部件:硬件部分和软件部分。硬件部分做些紧急的事,比如填充DPC队列,执行外设操作,软件部分处理硬件部分没有做完的事,比如将IO数据拷贝到用户空间。
因为硬件中断,其中断级比较高,肯定是在DISPATCH_LEVEL以上了,所以我们可以这样认为:由DISPATCH_LEVEL或其以下调整到其以上级别,那就是产生了硬件中断,这个调整动作由中断函数来完成,反之,由DISPATCH_LEVEL或其以上级别调整到DISPATCH_LEVEL级别以下,就认为软件中断发生。为什么这样认为?可以这样理解:硬件中断发生时,中断级别调整到DISPATCH_LEVEL以上,硬件中断完成后,中断级别当然要下来了,这个下调就触发了软中断,因为我们认定这个上调和下调的过程是发生了硬件中断,而软件中断是给硬件中断做后事处理的。
硬件中断是处理器自动执行的,这个比较容易理解,而软件中断也就是中断级别下调的过程,是软件模拟出来的, 是参与调度的。比如DPC执行就是在软件中断中做的。
软件中断是由高中断级别下调产生的,打个比方说,如果把DISPATCH_LEVEL当成二楼,PASSIVE_LEVEL当成一楼,那么从三楼(硬件中断级别)向下跳,跳到二楼和一楼那效果肯定是不一样的,所以这里有个软中断的行程问题,行程不同,则其功能也不同,具体可以看这个函数:
VOID FASTCALL
HalRequestSoftwareInterrupt( 这就是请求软件中断的函数
IN KIRQL Request)
{
switch (Request)
{
case APC_LEVEL:不同的中断级别表示不同的行程,其功能也不同。
((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE;
break;
case DISPATCH_LEVEL:
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE;
break;
default:
DbgBreakPoint();
}
}
注意:这里只是设置一个请求扫描的标志位,具体的DPC或APC例程还不是在这里执行的。那么DPC是在哪里执行的呢?就是当从硬件中断级别向软件中断级别下跳时,不管是跳到DPC还是APC,如果有软件中断请求,也就是上面的那个设置请求标志位的函数设置了True,内核就会扫描DPC请求队列并执行DPC函数。
个人感觉这样的名字设计不好,至少从字面意思上看着无法对应,HalRequestSoftwareInterrupt确切名字应该叫做:HalSetSoftwareRequestScanFlag。而真正执行DPC函数的地方是KeLowerIrql,同样不好的名字,从字面只能看到降低IRQL,看不到DPC函数的执行。而实际上,在KeLowerIrql中,会执行APC,DPC及定时器的扫描。