内核驱动核心概念:IRP、IRQL 与设备堆栈
IRP(I/O Request Packet,I/O 请求包)是 Windows 内核 I/O 系统的基础单元。用户态调用 ReadFile、WriteFile、DeviceIoControl 时,I/O 管理器会生成 IRP,沿着设备堆栈逐层下发给驱动。每个驱动可以选择处理 IRP,或者向下转发给下层驱动,处理完成后调用完成函数,把结果回传给上层。过滤驱动就是挂载在设备堆栈上,拦截、修改 IRP,常见于文件过滤、网络过滤。IRQL(中断请求级别)是内核并发控制机制。CPU 运行在不同 IRQL 层级,高 IRQL 代码可以抢占低 IRQL 代码。常见层级:PASSIVE_LEVEL(普通线程,可分页内存)、DISPATCH_LEVEL(调度级别,不能使用分页内存,不能调用会阻塞的函数)。开发中最容易踩坑:在 DISPATCH_LEVEL 调用分页内存 API,直接蓝屏。
设备堆栈:一个硬件设备会绑定多个驱动,形成从上到下的堆栈。上层过滤驱动、功能驱动、底层总线驱动依次排列。PnP 管理器负责构建、销毁设备堆栈,驱动必须正确响应 PnP 事件,否则设备无法正常加载。
楼主,不论什么情况你一定要hold住!hold住就是胜利! 果断回帖,如果沉了就是我弄沉的很有成就感 补充一个容易漏的点:设备堆栈往下传 IRP 时,完成例程注册之后不要再改这个 IRP 的栈位置。下层驱动可能已经在另一个 IRQL 上完成它了。需要带回结果的话,在调用 IoCallDriver 之前把上下文放进 IRP 的 DriverContext,完成例程里只读那一块。 不管你信不信,反正我是信了。 除了IRQL级别与内存分页问题,在内核完成例程中还需特别留意IRP挂起标志(PendingReturned)。如果下层驱动返回了STATUS_PENDING,当前层必须调用IoMarkIrpPending,否则上层等待容易引发死锁。 楼主,不论什么情况你一定要hold住!hold住就是胜利!
页:
[1]