IRP请求的完成与返回

 IRP请求的完成与返回


    每当完成了一个以IRP为代表的I/O操作请求的时候,就要执行IRP的善后操作IoCompleteRequest(),这是个宏操作,定义为函数IofCompleteRequest()。
#define  IoCompleteRequest  IofCompleteRequest
    如前所述,以IRP为代表的I/O操作请求的执行可以是同步的,也可以是异步的,所以一个I/O操作请求的完成不一定与相应主功能函数的返回相一致。如果操作是同步的,那么主功能函数要到完成了所要求的操作时才返回,所以在返回之前就要执行这个函数。如果操作是异步的,那么主功能函数不等所要求的操作完成就返回了,这个函数的执行就留给了DPC函数。
    IRP的善后包括一些什么操作呢?当然,这里面包括将其从IRP所属线程和所针对设备对象的IRP队列中摘除出来并加以释放,但是这还不是事情的全部。前面讲过,由于异步操作,各层设备驱动的主功能函数不等操作完成就返回了,可是各层设备驱动都可能有自己的善后函数,这些善后函数要等IRP所要求的操作完成时才能执行,所以就通过宏操作IoSetCompletionRoutine()设置好相应IO_STACK_LOCATION数据结构中的函数指针CompletionRoutine,把善后函数的执行托付给DPC函数。所以,IRP的善后就包括自下而上地扫描IRP中的各层IO_STACK_LOCATION数据结构,如果字段Control中相应标志位所表示的条件得到满足就加以调用。
    读者也许会问,如果各层设备驱动所实现的恰巧都是同步操作,那也要把善后函数托付给DPC函数吗?例如,在前面通过系统调用NtReadFile()读鼠标器的例子中,如果恰巧类设备对象的缓冲区中有数据可读,那么该操作实际上就是同步的。在这种情况下,各层设备驱动仍可以通过IoSetCompletionRoutine()设置IRP中的函数指针,但是最后执行IofCompleteRequest()的并不是DPC函数,而是当前线程。当前线程在完成了IRP所要求的操作以后就会执行IofCompleteRequest(),同样会自下而上地扫描执行各层设备驱动的善后函数。这样,当上一层设备驱动的函数从IoCallDriver()返回时,它所托付的善后函数已经得到执行了。

你可能感兴趣的:(数据结构,IO)