Handling IRPs 7: IoCompletion Routines and Asynchronous I/O Responses

IoCompletion Routines and Asynchronous I/O Responses

If a driver sets an IoCompletion routine for an IRP, the IoCompletion routine can check the value of the Irp->PendingReturned field to determine whether the IRP will be completed asynchronously.

If the value of the Irp->PendingReturned field is TRUE, the IoCallDriver routine will return (or has already returned) STATUS_PENDING. If Irp‑>PendingReturned is FALSE, IoCallDriver has already returned with the value in the Irp‑>IoStatus.Status field. IoCompletion routines for intermediate drivers can similarly test Irp‑>PendingReturned to determine how the result of their forwarded request is being handled.

Drivers that complete I/O requests asynchronously sometimes must perform additional processing as the IRP moves back up the device stack. The following code sets an IoCompletion routine when it forwards an IRP to the next lower driver, then waits on an event. Thus, it handles an asynchronous response in the same manner as a synchronous one:

KEVENT   event;

 

KeInitializeEvent(&event, NotificationEvent, FALSE);

 

IoCopyCurrentIrpStackLocationToNext(Irp);

 

IoSetCompletionRoutine(Irp,

                       CatchIrpRoutine,

                       &event,

                       TRUE,

                       TRUE,

                       TRUE

                       );

 

status = IoCallDriver(DeviceObject, Irp);

 

//

// Wait for lower drivers to be done with the Irp.

// It’s important to note here that when you allocate

// memory for an event on the stack you must do a

// KernelMode wait instead of UserMode to prevent

// the stack from being paged out.

//

 

    if (status == STATUS_PENDING) {

       status = KeWaitForSingleObject(&event,

                             Executive,

                             KernelMode,

                             FALSE,

                             NULL

                             );

       ASSERT(NT_SUCCESS(status));

       status = Irp->IoStatus.Status;

    }

 

return status;

 

In this case, the driver waits for an event that is set by its IoCompletion routine. The driver must wait in kernel mode because the event was allocated on the stack. For performance reasons, drivers should wait on events only when IRPs complete asynchronously. The KeWaitForSingleObject routine uses the system-wide dispatcher lock. This lock protects the signal state of events, semaphores, and mutexes, and consequently is used frequently throughout the operating system. Requiring the use of this lock for every synchronous I/O operation would unacceptably hinder performance.

The following code shows the IoCompletion routine set in the preceding fragment:

NTSTATUS

CatchIrpRoutine(

    IN PDEVICE_OBJECT    DeviceObject,

    IN PIRP       Irp,

    IN PKEVENT Event

    )

{

    if (IrpàPendingReturned) {

 

        // Release waiting thread

        KeSetEvent( Event, IO_NO_INCREMENT, FALSE );

    }

 

    return STATUS_MORE_PROCESSING_REQUIRED;

}

 

The IoCompletion routine tests the value of the Irp->PendingReturned field. Based on this value, it sets an event only if STATUS_PENDING has been or will be returned to the caller. This avoids a call to the KeSetEvent routine, which uses the system-wide dispatcher lock.

The IoCompletion routine returns STATUS_MORE_PROCESSING_REQUIRED. This status indicates to the I/O Manager that the current driver must perform additional processing while it owns the IRP. The I/O Manager stops the upward completion of the IRP, leaving the I/O stack location in its current position. The current driver still owns the IRP and can continue to process it in another routine. When the driver has completely processed the IRP, it should call the IoCompleteRequest routine to continue IRP completion.

Ownership of the IRP is important because it determines whether the driver can access the IRP. As soon as a driver relinquishes ownership of the IRP, the IRP can be completed or freed on another thread, and any attempt by the driver to access the IRP can result in a system crash. 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值