阅读:2015回复:4
由IoSetCompletionRoutine源代码引出的两点迷惑
1.
#define IoSetCompletionRoutine(irp,routine,completioncontext,success,error,cancel)\ #{ PIO_STACK_LOCATION irpsp;\ #ASSERT((success)|(error)|(cancel)?(routine)!=NULL:TRUE);\ #irpsp=IoGetNextIrpStackLocation((irp));\ #irpsp->completionroutine=(routine);\ #irpsp->context=(completioncontext);\ #irpsp->control=0;\ #if((success)){irpsp->control=SL_INVOKE_ON_SUCCESS;}\ #if((error)){irpsp->control |= SL_INVOKE_ON_ERROR;}\ #if((cancel)){irpsp->control |= SL_INVOKE_ON_CANCEL;} }\ 以上的定义中irpsp=IoGetNextIrpStackLocation((irp));为什么是IoGetNextIrpStackLocation,而不是IoCurrentIrpStackLocation?这是不是表示设置完成历程的驱动的下层驱动调用完成历程了了? 2. 书上说IO管理器给每层驱动都创建一个IRP堆栈,那么对于过滤驱动,也应该对应一层IRP堆栈单元A,在其passthrough中,调用iocalldriver前为什么有时还要调用ioskipcurrentirpstacklocation?IO管理器理应也为过滤驱动下层驱动准备了IRP堆栈单元B,直接iocalldriver,跳到此IRP堆栈单元B不就行了,如果ioskipcurrentirpstacklocation,那么下层驱动接收到的不也是IRP堆栈单元A了? |
|
沙发#
发布于:2008-08-23 22:02
我也想不通,居然跟我想的问题一样,帮你顶一下!
我是这样认为的: 因为必须在下层设备IO成功后,才会调用本层设备的完成例程,所以设置在下层设备栈中 |
|
板凳#
发布于:2008-08-24 00:11
对于第二个问题,真如你所说的,下层驱动接收到就是要堆栈单元A的数据,因为堆栈单元A的数据就是你过滤之后的,显然是下层需要的!
|
|
地板#
发布于:2009-01-31 13:06
第一个问题,IoGetNextIrpStackLocation仅仅是得到下层I/o堆栈,这跟谁调用完成例程有什么关系,再说,当irp完成之后,它会一层一层向上返回,如果遇到哪一层设置有完成例程,就在哪一层执行完成例程呗
第二个问题,当你本层驱动不需要对IRP执行任何操作的时候(改变它的属性),也就是把这个IRP原原本本的传给下层驱动就用ioskipcurrentirpstacklocation函数,如果改变了一些属性,就要用iocopycurrentirpstacklocation了 |
|
地下室#
发布于:2009-02-03 11:42
第一个问题,在向驱动链表的下一层驱动传递IRP之前,当前驱动有必要设置下一层IRP stack的信息。
|
|