Overview
Interrupts are the primary mechanism that the Windows kernel uses to respond to asynchronous events from hardware and software. An interrupt transfers control from the currently executing code to a predefined interrupt service routine (ISR) that handles the event.
Types of Interrupts
- Hardware Interrupts (IRQs) – Generated by peripheral devices via the Advanced Programmable Interrupt Controller (APIC).
- Software Interrupts (DPCs) – Deferred Procedure Calls that run at a lower IRQL after the ISR completes.
- Inter-Processor Interrupts (IPIs) – Used for communication between CPUs in a multiprocessor system.
Interrupt Handling
The kernel processes interrupts in several stages:
- ISR (Interrupt Service Routine) – Executes at high IRQL, performs minimal work, acknowledges hardware.
- DPC (Deferred Procedure Call) – Runs at DISPATCH_LEVEL, handles lengthy processing.
- Synchronisation – Uses spinlocks and IRQL masking to protect shared resources.
API Reference
Function | Description |
---|---|
KeInitializeInterrupt | Initialises a KINTERRUPT object. |
IoConnectInterrupt | Registers an ISR with the kernel. |
IoDisconnectInterrupt | Unregisters an ISR. |
KeRaiseIrql | Raises the current IRQL. |
KeLowerIrql | Lowers the IRQL. |
Example Code
#include <ntddk.h>
VOID MyIsr(
PKINTERRUPT Interrupt,
PVOID ServiceContext
)
{
UNREFERENCED_PARAMETER(Interrupt);
UNREFERENCED_PARAMETER(ServiceContext);
// Acknowledge hardware interrupt here
// Queue a DPC for further processing
KeInsertQueueDpc(&MyDpc, NULL, NULL);
}
VOID MyDpc(
KDPC *Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2
)
{
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(DeferredContext);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
// Perform lengthy work safely at DISPATCH_LEVEL
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
PKINTERRUPT interruptObject = NULL;
NTSTATUS status;
// Register ISR
status = IoConnectInterrupt(
&interruptObject,
MyIsr,
NULL,
NULL,
0, // Vector (auto-assigned)
DIRQL,
DIRQL,
LevelSensitive,
TRUE,
0,
FALSE
);
if (!NT_SUCCESS(status))
return status;
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}