当前位置: 首页 > news >正文

Windows 驱动程序中不同函数运行在不同的中断请求级别 (IRQL)详细的分类

IRQL 级别说明

PASSIVE_LEVEL (0)

  • 最低优先级,可以被任何中断打断
  • 可以访问分页内存,可以等待

常用函数:

// 文件操作
ZwCreateFile()
ZwReadFile()
ZwWriteFile()
ZwClose()
ZwQueryInformationFile()
ZwSetInformationFile()// 注册表操作
ZwOpenKey()
ZwQueryValueKey()
ZwSetValueKey()
ZwClose()// 内存管理
ZwAllocateVirtualMemory()
ZwFreeVirtualMemory()
ZwMapViewOfSection()
ZwUnmapViewOfSection()// 线程和进程
PsCreateSystemThread()
PsTerminateSystemThread()
ZwWaitForSingleObject()
ZwWaitForMultipleObjects()// 同步对象
KeWaitForSingleObject()
KeWaitForMultipleObjects()
KeDelayExecutionThread()// 驱动程序框架
DriverEntry()
DriverUnload()
AddDevice()

APC_LEVEL (1)

  • 异步过程调用级别
  • 不能等待内核对象

常用函数:

// 异步过程调用
KeInsertQueueApc()
KeFlushQueuedDpcs()// 某些内存操作
ExAllocatePoolWithTag() // 可能运行在APC_LEVEL
ExFreePoolWithTag()

DISPATCH_LEVEL (2)

  • 调度级别,高优先级
  • 不能访问分页内存,不能等待

常用函数:

// DPC 相关
KeInsertQueueDpc()
KeRemoveQueueDpc()
KeFlushQueuedDpcs()// 计时器
KeSetTimer()
KeCancelTimer()
KeSetTimerEx()// 自旋锁
KeAcquireSpinLock()
KeReleaseSpinLock()
KeAcquireSpinLockAtDpcLevel()
KeReleaseSpinLockFromDpcLevel()// 中断相关
KeAcquireInterruptSpinLock()
KeReleaseInterruptSpinLock()
KeSynchronizeExecution()// 内存操作(非分页)
RtlCopyMemory()
RtlZeroMemory()
RtlMoveMemory()// 链表操作
InsertTailList()
RemoveEntryList()
IsListEmpty()// 原子操作
InterlockedIncrement()
InterlockedDecrement()
InterlockedExchange()
InterlockedCompareExchange()

DIRQL (Device IRQL, 3-31)

  • 设备中断级别
  • 最高优先级,不能被低级别中断打断

常用函数:

// 中断服务例程
InterruptServiceRoutine()// 硬件访问
READ_PORT_UCHAR()
WRITE_PORT_UCHAR()
READ_REGISTER_ULONG()
WRITE_REGISTER_ULONG()// 原子操作
InterlockedIncrement()
InterlockedDecrement()
InterlockedExchange()// 简单的内存操作
RtlCopyMemory()
RtlZeroMemory()

实际代码示例

// PASSIVE_LEVEL 示例
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{// 当前 IRQL = PASSIVE_LEVELKIRQL currentIrql = KeGetCurrentIrql();DbgPrint("DriverEntry IRQL: %d\n", currentIrql);// 可以调用文件操作HANDLE fileHandle;NTSTATUS status = ZwCreateFile(&fileHandle, ...);// 可以等待LARGE_INTEGER timeout;timeout.QuadPart = -10000000; // 1秒KeDelayExecutionThread(KernelMode, FALSE, &timeout);return STATUS_SUCCESS;
}// DISPATCH_LEVEL 示例
VOID MyDpcRoutine(PKDPC Dpc,PVOID DeferredContext,PVOID SystemArgument1,PVOID SystemArgument2
)
{// 当前 IRQL = DISPATCH_LEVELKIRQL currentIrql = KeGetCurrentIrql();DbgPrint("DPC IRQL: %d\n", currentIrql);// 只能调用非分页函数KIRQL oldIrql;KeAcquireSpinLock(&MySpinLock, &oldIrql);// 处理数据ProcessDataAtDispatchLevel();KeReleaseSpinLock(&MySpinLock, oldIrql);
}// DIRQL 示例
BOOLEAN MyInterruptServiceRoutine(PKINTERRUPT Interrupt,PVOID ServiceContext
)
{// 当前 IRQL = DIRQL (高于 DISPATCH_LEVEL)// 只能进行最基本的操作ULONG data = READ_PORT_ULONG(DevicePort);// 快速处理,可能排队DPCKeInsertQueueDpc(&MyDpc, NULL, NULL);return TRUE; // 中断已处理
}

IRQL 检查和调试

// 检查当前 IRQL
KIRQL GetCurrentIRQL(VOID)
{return KeGetCurrentIrql();
}// 安全的 IRQL 检查
BOOLEAN IsIrqlSafeFor(OPERATION_TYPE operation)
{KIRQL currentIrql = KeGetCurrentIrql();switch (operation) {case FILE_OPERATION:return (currentIrql <= PASSIVE_LEVEL);case MEMORY_ALLOCATION:return (currentIrql <= DISPATCH_LEVEL);case SPINLOCK_OPERATION:return (currentIrql <= DISPATCH_LEVEL);case PORT_ACCESS:return TRUE; // 所有级别都可以default:return FALSE;}
}// 临时提升 IRQL
VOID RaiseIrqlExample(VOID)
{KIRQL oldIrql;// 提升到 DISPATCH_LEVELKeRaiseIrql(DISPATCH_LEVEL, &oldIrql);// 在高 IRQL 下执行操作// 注意:不能访问分页内存或等待// 恢复原来的 IRQLKeLowerIrql(oldIrql);
}

常见的 IRQL 错误

// 错误示例1:在高 IRQL 下调用分页函数
VOID BadDpcRoutine(PKDPC Dpc, PVOID Context, PVOID Arg1, PVOID Arg2)
{// 当前 IRQL = DISPATCH_LEVEL// 错误!不能在 DISPATCH_LEVEL 调用可能分页的函数NTSTATUS status = ZwCreateFile(&handle, ...); // 会导致 BSOD
}// 错误示例2:在高 IRQL 下等待
VOID BadWaitAtHighIrql(VOID)
{KIRQL oldIrql;KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);// 错误!不能在 DISPATCH_LEVEL 等待KeWaitForSingleObject(&MyEvent, Executive, KernelMode, FALSE, NULL);KeLowerIrql(oldIrql);
}

最佳实践

  1. 始终检查当前 IRQL
  2. 使用 PAGED_CODE() 宏标记可分页代码
  3. 在高 IRQL 下快速完成操作
  4. 使用 DPC 将工作推迟到较低 IRQL
  5. 正确管理自旋锁和 IRQL 级别

这些知识对于编写稳定的 Windows 驱动程序非常重要!

http://www.xdnf.cn/news/1096525.html

相关文章:

  • 正点原子 文件权限
  • 聊一聊跨浏览器测试验证点梳理
  • 搜索引擎vs向量数据库:LangChain混合检索架构实战解析
  • 数据提取之bs4(BeautifuSoup4)模块与Css选择器
  • 使用Word/Excel管理需求的10个痛点及解决方案Perforce ALM
  • CMD,PowerShell、Linux/MAC设置环境变量
  • 主从IO核心
  • Transformers 和 PyTorch 的区别与安装指南
  • Flowable23手动、接收任务----------持续更新中
  • 【计算机基础理论知识】C++篇(二)
  • codeforeces Round1032 - Round 1036
  • 学习笔记(32):matplotlib绘制简单图表-数据分布图
  • Linux Vim 编辑器详解:从入门到进阶(含图示+插件推荐)
  • Java从入门到精通!第三天(数组)
  • 【threejs】第一人称视角之八叉树碰撞检测
  • 论文笔记(LLM distillation):Distilling Step-by-Step!
  • MiniGPT4源码拆解——models
  • 原生微信小程序研发,如何对图片进行统一管理?
  • 微信小程序101~110
  • UnrealEngine5游戏引擎实践(C++)
  • Android Coil 3 data加载图的Bitmap或ByteArray数据类型,Kotlin
  • Android 如何阻止应用自升级
  • C语言 | 函数核心机制深度解构:从底层架构到工程化实践
  • Matplotlib 全面使用指南 -- 自动缩放坐标轴 Autoscaling Axis
  • 【Linux】Linux 操作系统 - 27 , 进程间通信(三) --System V 共享内存
  • 编写bat文件自动打开chrome浏览器,并通过selenium抓取浏览器操作chrome
  • 抽象类基础知识
  • 如何选择合适的ai降重工具?七个实用的ai查重网站
  • 【会员专享数据】2013-2024年我国省市县三级逐日SO₂数值数据(Shp/Excel格式)
  • 告别繁琐:API全生命周期管理的新范式——apiSQL