如何执行完成处理

注意

为了获得最佳可靠性和性能,请使用支持筛选器管理器的 文件系统微筛选器驱动程序 ,而不是旧的文件系统筛选器驱动程序。 若要将旧驱动程序移植到微筛选器驱动程序,请参阅 移植旧版筛选器驱动程序指南

完成处理分两个阶段执行。 第一个阶段在任意线程上下文中执行,在 IRQL <= DISPATCH_LEVEL。 在此阶段中,将执行以下任务:

  • 依次调用为 IRP 注册的每个完成例程,从最低 IRP 堆栈位置开始。 如果完成例程返回STATUS_MORE_PROCESSING_REQUIRED,则完成处理将停止。

  • 如果 IRP 包含内存描述符列表 (MDL) ,则 MDL 映射的任何物理页都将解锁。

  • I/O 完成的第二阶段将排到目标 (请求) 线程作为特殊内核 APC。

第二个阶段在发起 I/O 请求的线程的上下文中执行。 它作为特殊内核 APC 执行,因此在 IRQL APC_LEVEL运行。 在此阶段中,将执行以下任务:

  • 如果 IRP 表示缓冲的操作,则 Irp-AssociatedIrp.SystemBuffer> 的内容将复制到 Irp-UserBuffer>

  • 如果 IRP 包含 MDL,则释放 MDL。

  • Irp-IoStatus> 的内容将复制到 Irp-UserIosb>,以便 I/O 请求的发起方可以查看操作的最终状态。

  • 如果在 Irp-UserEvent> 中提供了事件,则会发出信号。 否则,如果此 IRP 有一个文件对象,则会向其事件发出信号。

  • 如果 IRP 是通过调用 IoBuildDeviceIoControlRequestIoBuildSynchronousFsdRequest 创建的,则会将其从线程的挂起 I/O 请求列表中取消排队。

  • 如果用户 APC 已排队(如果调用方请求)。

  • IRP 已释放。

如果由于STATUS_MORE_PROCESSING_REQUIRED返回的完成例程而停止了 IRP 的完成处理,可以通过在同一 IRP 上调用 IoCompleteRequest 来恢复该处理。 发生这种情况时,第一阶段处理会恢复,从驱动程序的完成例程开始,紧靠其完成例程返回STATUS_MORE_PROCESSING_REQUIRED。