能力值:
( LV12,RANK:450 )
|
-
-
2 楼
1.IoSetCompletionRoutine本来就是构造IRP后往下层驱动传递IRP的时候设置的一个完成函数。
|
能力值:
( LV4,RANK:50 )
|
-
-
3 楼
第一个问题:我个人理解,每一个IRP动作完成后,如果上层有设置完成例程,那么就调用完成例程,个人认为当前的IrpStackLocation 对应的是上层的完成例程的函数指针。而且IoSetCompletionRoutine只是去设置下层这个值,并没有跳到下层去。
第二个问题:
#define IoSkipCurrentIrpStackLocation( Irp ) \
(Irp)->CurrentLocation++; \
(Irp)->Tail.Overlay.CurrentStackLocation++;
|
能力值:
( LV4,RANK:50 )
|
-
-
4 楼
重新看了IoCallDriver的源码学习理解如下:
NTSTATUS
FASTCALL
IopfCallDriver(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
PIO_STACK_LOCATION irpSp;
PDRIVER_OBJECT driverObject;
NTSTATUS status;
//
// Ensure that this is really an I/O Request Packet.
//
ASSERT( Irp->Type == IO_TYPE_IRP );
//
// Update the IRP stack to point to the next location.
//
Irp->CurrentLocation--;//每次调用IoCallDriver CurrentLocation都会减去1
if (Irp->CurrentLocation <= 0) {
KeBugCheckEx( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0, 0 );
}
irpSp = IoGetNextIrpStackLocation( Irp );
Irp->Tail.Overlay.CurrentStackLocation = irpSp;
//
// Save a pointer to the device object for this request so that it can
// be used later in completion.
//
irpSp->DeviceObject = DeviceObject;
//
// Invoke the driver at its dispatch routine entry point.
//
driverObject = DeviceObject->DriverObject;
PERFINFO_DRIVER_MAJORFUNCTION_CALL(Irp, irpSp, driverObject);
status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject,
Irp );
PERFINFO_DRIVER_MAJORFUNCTION_RETURN(Irp, irpSp, driverObject);
return status;
}
每次IoCallDriver的时候,系统会自动将CurrentIrpStackLocation减去1,指向下一个IO_STACK_LOCATION
|
能力值:
( LV4,RANK:50 )
|
-
-
5 楼
IoSkipCurrentIrpStackLocation是将这个指针移回来,实现平衡。
|
能力值:
( LV12,RANK:450 )
|
-
-
6 楼
在csdn上有人讲到:IoSetCompletionRoutine()函数的作用是设置完成例程,也就是将该irp向下层传递,让下层处理.下层处理完返回时触发刚才设置的完成例程,从而又有了处理该irp的机会.
|
能力值:
( LV4,RANK:50 )
|
-
-
7 楼
如果你的驱动程序不用关心IRP传递到下层驱动程序之后的事情,你可以利用一个捷径来避免复制堆栈单元。在这种情形下,我们不需要安装完成例程。
没有必要花费处理器时间去把你的堆栈单元内容复制到下一个堆栈单元,因为那个堆栈单元已经含有下一层驱动程序要得到的参数,以及自己上一层驱动程序可能给出的任何完成例程指针。因此,你可以使用下面捷径方法:
NTSTATUS ForwardAndForget(PDEVICE_OBJECT fdo, PIRP Irp)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
这个捷径存在于IoSkipCurrentIrpStackLocation函数(它实际上是一个宏,名字有些另人误解)中。这个宏的作用就是使堆栈指针少前进一步,而IoCallDriver函数会使堆栈指针向前一步,中和的结果就是堆栈指针不变。当下一个驱动程序的派遣例程调用IoGetCurrentIrpStackLocation时,它将收到与我们正使用的完全相同的IO_STACK_LOCATION指针,因此,它所处理的将是同一个请求(相同的主副功能代码)以及相同的参数。
|
|
|