What is IRQL?
IRQL is the interrupt request level and the interrupt request level. The processor executes the thread code on an IRQL. IRQL helps determine how a thread is interrupted. On the same processor, a thread can only be interrupted by a higher-level IRQL thread. Each processor has its own interrupt IRQL.
We often see four IRQL levels. "Passive", "APC", "dispatch" and "dirql ".
"DriverEntry" will be called at passive_level.
# Define passive_level 0
# Define low_level 0
# Define apc_level 1
# Define dispatch_level 2
# Define profile_level 27
# Define clock1_level 28
# Define clock2_level 28
# Define ipi_level 29
# Define power_level 30
# Define high_level 31
Passive_level
At the lowest level of IRQL, there is no blocked interruption. At this level, the thread executes the user mode and can access the paging memory.
Apc_level
At this level, only APC-level interruptions are blocked and paging memory can be accessed. When an APC occurs, the processor is upgraded to the APC level. In this way, other APC will be blocked. To perform some synchronization with the APC, the driver can be manually upgraded to this level. For example, if it is upgraded to this level, APC cannot be called. At this level, APC is disabled, and some I/O operations are prohibited, so some APIs cannot be called.
Dispatch_level
At this level, DPC (latency process) and lower interruptions are blocked, and paging memory cannot be accessed, and all accessed memory cannot be paged. Because only non-Paging memory can be processed, at this level, the number of APIs that can be accessed is greatly reduced.
Dirql (device IRQL)
Generally, drivers at a high level do not use this IRQL level, and all interruptions at this level are ignored. This is the highest level of IRQL. This is usually used to determine the priority of a device.
Generally, more advanced drivers do not process IRQL at this level, but almost all interruptions are blocked. This is actually a range of IRQL, this is a method that determines that a driver has a higher priority.
1.3.1 kernel code running level
Windows NT assigns different levels for its kernel-mode code. Low-level processes on the same CPU
Can be interrupted by any larger process. The levels are listed as follows:
Process where the level name runs at this level
Passive_level DriverEntry, unload, shutdown, dispatchxxx.
In some special circumstances, the driver of a large storage device runs at this level.
Dispatch_level startio, adaptercontrol, controllercontrol, iotimer, and DPC.
Dirqls various interrupt handling programs.
Table 16.1 default IRQL of driver routines
IRQL (from low to high) blocked interrupt running this IRQL support routine
Passive_level has no dispatch, DriverEntry, adddevice, reinitialize, unload routine, thread created by the driver, work-thread callback, and file system driver.
Dispatch_level and apc_level are blocked. Device, clock, and power supply failure can still occur
Startio, adaptercontrol, adapterlistcontrol, controllercontrol, iotimer, cancel (when undo spin lock is held), dpcforisr, customtimerdpc, customdpc routine
All IRQL <= dirql interruptions in the dirql driver interrupt object. ISR and synccritsection routines can still occur when the clock and power supply are interrupted.
One or more iocompletion routines may be required for high-level drivers. At least I/O status blocks are checked and iocompleterequest is called. If necessary, modify the data structure and content of device extension. One thing that must be clear is the code running level, namely IRQL. The most common levels are passive_level, apc_level, dispatch_level, and dirql.
When looking at the function description in nt ddk help, pay attention to the runability level of the function. For example, some functions can only run under passive_level, and some functions can run at or below dispatch_level, the higher the level, the stricter the Code requirements. For example, when dispatch_level is used, paging memory cannot be used. Generally, you should try to run the code at a low level such as passive_level. If the code runs at a high level for a long time, the system efficiency will be reduced and the system response timeliness will be affected. However, sometimes you cannot control the running level. For example, if you use iocalldriver when calling the lower-layer driver, the lower-layer driver will execute the completion routine after the response is complete. The running level of this routine is determined by the lower-layer driver. Therefore, when writing a completion routine, try to design this function to run at the dispatch_level level.