2.2 IRP处理
I/O请求包(IRP)是驱动程序操作的中心,是一个预先定义的数据结构,带有一组对它进行操作的I/O管理器例程。一个IRP有固定的首部和可变数目的 IRP栈单元。IRP的固定部分含有IRP的固定属性,每个栈单元含有大多数有关的IRP参数。当IRP由多个驱动程序处理时,使用多个IRP栈单元。每个驱动程序从当前IRP栈单元得到它的IRP参数。如果把IRP沿当前设备的驱动程序栈向下传递,必须在当前驱动程序中使用正确的参数设置下一个栈单元,然后在此驱动程序中利用函数IoCalldriver()调用更低层的驱动程序。驱动程序不必处理所有的IRP,但至少需要处理“创建”和“关闭”这两个 IRP。I/O管理器接收I/O请求,然后在把它传递到合适的驱动程序栈中的最高驱动程序之前,分配并初始化IRP。驱动程序处理IRP的过程如图2所示。
IR
P首先到达最高层的驱动程序1,驱动程序1使用函数IoGetCurrentIrpStackLocation()获得指向当前栈单元的指针。
然后驱动程序1使用IoCallDriver()函数调用下一个驱动程序。I/O管理器现在改变“当前IRF’栈单元”指针,所以驱动程序2看到向下的第二个IRP栈单元(驱动程序1为它设置的栈单元)。这个过程继续,直到最底层的的驱动程序4收到这个IRP。
驱动程序4现在处理这个IRP。当它完成IRP的处理时,驱动程序4调用IoCompleteRequest()函数。指示它已经完成IRP的处理。IRP再沿设备栈向上传递,直到它最终弹出栈顶,回到用户。
2.3 IRP的完成
当一个驱动程序完成对IRP的处理时,它必须告诉I/O管理器,这称为IRP完成。如下面代码所示,必须设置IRP IoStatus域结构中的几个域。IoStatus,Status设置为一个NTSTATUS状态码,IoStatus.In-formation通常存储传输的字节数。如:
Irp一>loStatus.Status=S T ATUS_SUCCESS
Irp一>IoStatus.Information=info;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
调用IoCompleteRequest()表明低层驱动程序已经完成了IRP的请求,并将这个IRP返回给I/O管理器。IO_No_INCREMENT是个系统定义的常量,指定启动该IRP的优先级,需要驱动程序快速处理。