同步(2)
这节我们来讨论中断级(IRQL)。
关于中断级的概念,还有一些基础的知识,请参考前面我写的章节。这里不再重复。
笔者以前说过,运行在低中断级的代码是没有能力打断运行在高中断级的代码的执行。那么为什么微软要有这个限制?这样的特性有什么用?为什么中断级和同步会扯上关系?这些问题我一会慢慢解释
我们知道,中断分硬件中断,和软件中断两类。硬件中断还分可屏蔽和不可屏蔽。不可屏蔽中断是由CPU引脚(NMI)来接受。而可屏蔽中断是通过CPU引脚(INTR)来接受。关于不可屏蔽中断,我们不研究。我们只研究可屏蔽中断。可能读者会问为什么不研究不可屏蔽中断呀?道理很简单,我也不会!关于可屏蔽中断,涉及到2个8259A芯片,这2个芯片属于主从关系连结在一起之后再与CPU的INTR引脚相连。这2个芯片可以接受16个中断信号(分别接收8个)。以上说的是传统的机器。(以上之作了解,不必记忆)
现代的机器使用的是APIC(高级可编程控制器),一方面它兼容传统的方式,另一方面它把中断信号的个数扩展到24个。一旦某个中断发生,就会触发相对应的中断处理程序。现在这里有24个中断,那么系统中就会有24个中断处理程序。需要重点注意的是:这24个中断处理程序的中断级都是不同的。
现代机器的系统中都规定有32个中断级(0~31),其中数值越大,中断级越高。其中:
0----PASSIVE_LEVEL
1----APC_LEVEL
2----DISPATCH_LEVEL
3..........25之间的中断级正好对应上面说的24个硬件中断
26-----PROFILE_LEVEL
27----CLOCK1_LEVEL
28----CLOCK2_LEVEL
29----IPI_LEVEL
30----POWER_LEVEL
31----HIGH_LEVEL
其中0,1,2这3个中断级和软件中断有关。3到25和可屏蔽硬件中断有关。26到31和不可屏蔽硬件中断有关
而驱动程序中,我们只关心0,1,2这3个软件中断。因此以上信息也是只作了解。懂这个意思就行啦。
下面内容请务必记熟,我们继续
现在PASSIVE,APC,DISPATCH这3个家伙逐渐的浮出了水面,进入了我们视野。
首先,凡是应用程序线程都运行在PASSIVE中断级。驱动程序线程也运行在这个中断级的(或许中途临时提高中断级,但是还必须降下来)。驱动程序中DriverEntry,AddDevice,派遣函数一般都运行在PASSIVE中断级上(也可以临时提高,但还必须降下来)
windows中负责线程调度的代码运行在DISSPATCH中断级上,驱动程序的完成函数和StartIo函数也运行在DISSPATCH中断级上。
我一直强调一个概念:“代码仅仅是代码,函数仅仅是函数,他们是不会分高级还是低级。请注意我最上面用红字写的那段话”
一会找个例子证明这个观点。
到目前为止,中断级这块知识可以算告一段落。还请读者回忆下我以前讲过的知识点(内存管理4)。
几个和中断级有关的函数:
1,KeGetCurrentIrql():无参数,得到当前线程,当前时刻,当前代码所处的中断级
2,KeRaiseIrql(ULONG TargetLevel,PKIRQL
OldIrql)
3,KeLowerIrql(KIRQL OldIrql)
用法很简单:
VOID test()
{
KIRQL
OldIrql;
ASSERT(KeGetCurrentIrql()<=DISPATCH_LEVEL);
/ 如果当前中断级小于DISPATCH的话,提醒一下
KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
/提升中断级到DISPATCH,为了将来还原,保留原始的中断级
........
.......自己想要加入的代码
KeLowerIrql(OldIrql); /一定要还原。不然只要这个线程没有结束,其他线程将得不到运行,后果很严重
}
**************************************开始介绍自旋锁***************************************