新手关于IoMarkIrpPending作用的疑问,望达人解惑
近日读《Programming the Microsoft Windows Driver Model》,其中第5章《I/O请求包》- 第3节《完成I/O请求》- 最后一段介绍了何时需使用函数IoMarkIrpPending
我想问下几个问题
1. 异步Irp是不是无论PendingReturnd设置与否,驱动的完成例程都是在APC里调用的?
2. 同步Irp的完成例程是不是根据PendingReturned来判断需不需要APC?
3. PendingReturned和IoMarkIrpPending是不是为了优化同步Irp的完成效率,也就是在有些时候避免APC而存在的?
[解决办法]
1. 排队一个APC是相对昂贵的。设想一下,不是直接返回STATUS_PENDING,而是派遣例程自己调用IoCompleteRequest并返回某个其它状态。在这种情况下,IoCompleteRequest的调用者将与IoCallDriver的调用者处于同一个线程上下文中。因此就没有必要排队一个APC。另外,甚至没有必要调用KeSetEvent,因为如果I/O管理器没有得到派遣例程返回的STATUS_PENDING,它就不用等待某个事件。如果IoCompleteRequest恰好知道发生的这种情况,它将优化这个处理以避免调用APC。这就是IoMarkIrpPending的来处。
2.IoCompleteRequest查看PendingReturned标志。如果该标志设置,并且如果IRP是那种可以以异步方式完成的IRP,那么IoCompleteRequest将简单地返回其调用者并不排队APC。它假定自己运行在IRP发起者的线程上下文中,并且派遣例程很快会返回一个非未决状态的代码给请求发起者。
3.调用IoMarkIrpPending然后同步完成IRP是正确的,效率会低一点。这样做的结果是IoCompleteRequest将排队APC,这个APC将改变事件的状态,但没有任何线程在这个事件上等待(其目的是使在调用KeSetEvent前保证这个事件存在)。这会降低一些效率,但不会有什么害处。