在现代操作系统当中,驱动并不是固定与中断相对应的,而是作为一种资源由程序员自己在驱动当中申请,这样在驱动加载之后,如果有中断产生的时候,就会调用在与中断相关的函数。在驱动里面申请中断的系统函数原型如下面所示:
NTSTATUS
NTAPI
IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject,
IN PKSERVICE_ROUTINE ServiceRoutine,
IN PVOID ServiceContext,
IN PKSPIN_LOCK SpinLock,
IN ULONG Vector,
IN KIRQL Irql,
IN KIRQL SynchronizeIrql,
IN KINTERRUPT_MODE InterruptMode,
IN BOOLEAN ShareVector,
IN KAFFINITY ProcessorEnableMask,
IN BOOLEAN FloatingSave)
其中,第一个参数InterruptObject是申请中断对象指针的指针,这里不需要分配内存,只需要这个指针在非换页内存当中就可以了;第二个参数是在中断的时候想要调用的函数,第三个参数是作为第二个参数调用的时候的参数指针,第四个参数是中断对象当中的自旋锁,第五个是参数是中断向量号,用于找到相应的IDT项目,第六个参数用于标志本中断对象所处的IRQL,第七个参数用于多个中断对象共享一个中断的情况下,当出现多个中断共享一个中断的时候,这个参数标志中断能够运行的IRQL,并且这个IRQL必须必所有的DIRQL都要高,否则可能出现中断自身的现象,第九个参数用于标志中断的方式(类似于上一篇博客里面讲到的EPOLL的水平出发和边缘触发),第十个参数用于标志中断是否可以和其他的中断共享,第十一个参数用于标志中断处理的亲和性,第十二个参数用于在中断的时候是否可以保存浮点数,在X86架构下基本上都是FALSE——X86下面的中断处理不能保存浮点数的寄存器。
NTSTATUS
NTAPI
IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject,
IN PKSERVICE_ROUTINE ServiceRoutine,
IN PVOID ServiceContext,
IN PKSPIN_LOCK SpinLock,
IN ULONG Vector,
IN KIRQL Irql,
IN KIRQL SynchronizeIrql,
IN KINTERRUPT_MODE InterruptMode,
IN BOOLEAN ShareVector,
IN KAFFINITY ProcessorEnableMask,
IN BOOLEAN FloatingSave)
{
PKINTERRUPT Interrupt;
PKINTERRUPT InterruptUsed;
PIO_INTERRUPT IoInterrupt;
PKSPIN_LOCK SpinLockUsed;
BOOLEAN FirstRun;
CCHAR Count = 0;
KAFFINITY Affinity;
PAGED_CODE();
*InterruptObject = NULL;
Affinity = ProcessorEnableMask & KeActiveProcessors;//这个处理用于找到处于活动的处理器,其中每一位用于标志一个处理器,
while (Affinity) //其中我们传进来的参数用于在哪一个处理器上面进行中断处理
{
if (Affinity & 1) Count++;
Affinity >>= 1;
}
if (!Count) return STATUS_INVALID_PARAMETER;
IoI