45fan.com - 路饭网

搜索: 您的位置主页 > 电脑频道 > 电脑教程 > 阅读资讯:《Windows NT FileSystemInternals》学习笔记知识

《Windows NT FileSystemInternals》学习笔记知识

2016-09-04 11:48:16 来源:www.45fan.com 【

《Windows NT FileSystemInternals》学习笔记知识

原来以为完成IRP的处理仅仅是简单的调用一下IoCompleteRequest()函数而已,内部的代码应该很简单。阅读了Win2K源代码才发现,事情并不简单啊,呵呵,再一次发现Win2K源代码的价值了。

 

 

 

驱动必须调用IoCompleteRequest()通知I/O管理器相应的IRP已经处理完毕。IoCompleteRequest函数的处理过程如下(对应着Win2K源代码阅读,在ioStubs.c)

 

 

IoCompleteRequest调用过程如下:

 

IoCompleteRequestàIofCompleteRequestàIopfCompleteRequest(不知道微软的函数调用经过这么多过程干吗)àIopCompleteRequest(APC执行)

 

 

 

1. I/O管理器执行一些基本检查确保IRP在正确的状态。当前StackLocation的值必须小于等于StacksCount+1。如果该值不正确,系统返回错误码为MULTIPLE_IRP_COMPLETE_REQUESTbugcheck。如果安装的是debug build版本的操作系统,I/O管理器将执行一些附加的Assertion,例如检查STATUS_PENDING的返回状态码,以及其他从驱动返回值,

 

//

// Begin by ensuring that this packet has not already been completed

// by someone.

//

if (Irp->CurrentLocation > (CCHAR) (Irp->StackCount + 1) ||

Irp->Type != IO_TYPE_IRP) {

KeBugCheckEx( MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR) Irp, __LINE__, 0, 0 );

}

//

// Ensure that the packet being completed really is still an IRP.

//

ASSERT( Irp->Type == IO_TYPE_IRP );

//

// Ensure that no one believes that this request is still in a cancelable

// state.

//

ASSERT( !Irp->CancelRoutine );

//

// Ensure that the packet is not being completed with a thoroughly

// confusing status code. Actually completing a packet with a pending

// status probably means that someone forgot to set the real status in

// the packet.

//

ASSERT( Irp->IoStatus.Status != STATUS_PENDING );

//

// Ensure that the packet is not being completed with a minus one. This

// is apparently a common problem in some drivers, and has no meaning

// as a status code.

//

ASSERT( Irp->IoStatus.Status != 0xffffffff );

//

// Ensure that if this is a paging I/O operation, and it failed, that the

// reason for the failure isn't because quota was exceeded.

//

ASSERT( !(Irp->Flags & IRP_PAGING_IO && Irp->IoStatus.Status == STATUS_QUOTA_EXCEEDED ) );

 

 

 

2. I/O管理器开始扫描IRP包含的所有需要调用的Completion Routine。每一个Stack Location都可以包含一个Completion Routine,这些Completion Routine可以在IRP处理返回成功、错误或者取消时调用。I/O Stack Location采用反向顺序扫描,最高StackLocation最先扫描。这样磁盘驱动(最底层)提供的Completion Routine将最先调用,而最高层驱动的Completion Routine最后调用。

 

 

Completion Routine在调用IoCompleteRequest()的线程上下文中调用,如果某个Completion Routine返回STATUS_MORE_PROCESSION_REQUIREDI/O管理器停止IRP事后处理,将程序控制权返回调用IoCompleteRequeset()的程序。返回STATUS_MORE_PROCESSING_REQUIRED程序负责调用FreeIrp()

 

//

// Now check to see whether this is the last driver that needs to be

// invoked for this packet. If not, then bump the stack and check to

// see whether the driver wishes to see the completion. As each stack

// location is examined, invoke any routine which needs to be invoked.

// If the routine returns STATUS_MORE_PROCESSING_REQUIRED, then stop the

// processing of this packet.

//

for (stackPointer = IoGetCurrentIrpStackLocation( Irp ),

Irp->CurrentLocation++,

Irp->Tail.Overlay.CurrentStackLocation++;

Irp->CurrentLocation <= (CCHAR) (Irp->StackCount + 1);

stackPointer++,

Irp->CurrentLocation++,

Irp->Tail.Overlay.CurrentStackLocation++) {

//

// A stack location was located. Check to see whether or not it

// has a completion routine and if so, whether or not it should be

// invoked.

//

// Begin by saving the pending returned flag in the current stack

// location in the fixed part of the IRP.

//

Irp->PendingReturned = stackPointer->Control & SL_PENDING_RETURNED;

if ( (NT_SUCCESS( Irp->IoStatus.Status ) &&

stackPointer->Control & SL_INVOKE_ON_SUCCESS) ||

(!NT_SUCCESS( Irp->IoStatus.Status ) &&

stackPointer->Control & SL_INVOKE_ON_ERROR) ||

(Irp->Cancel &&

stackPointer->Control & SL_INVOKE_ON_CANCEL)

) {

//

// This driver has specified a completion routine. Invoke the

// routine passing it a pointer to its device object and the

// IRP that is being completed.

//

ZeroIrpStackLocation( stackPointer );

PERFINFO_DRIVER_COMPLETIONROUTINE_CALL(Irp, stackPointer);

status = stackPointer->CompletionRoutine( (PDEVICE_OBJECT) (Irp->CurrentLocation == (CCHAR) (Irp->StackCount + 1) ? (PDEVICE_OBJECT) NULL :IoGetCurrentIrpStackLocation( Irp )->DeviceObject), Irp,stackPointer->Context );

PERFINFO_DRIVER_COMPLETIONROUTINE_RETURN(Irp, stackPointer);

if (status == STATUS_MORE_PROCESSING_REQUIRED) {

//

// Note: Notice that if the driver has returned the above

// status value, it may have already DEALLOCATED the

// packet! Therefore, do NOT touch any part of the

// IRP in the following code.

//

return;

}

}

else

{

if (Irp->PendingReturned && Irp->CurrentLocation <= Irp->StackCount)

{

IoMarkIrpPending( Irp );

}

ZeroIrpStackLocation( stackPointer );

}

}

 

 

 

3. 如果IRP有相应的Associated IRPI/O管理器将递减AssociatedIrp.IrpCount字段的值,接着调用IopFreeIrpAndMdls()释放Associated IRP占用的内存和为它分配的MDL结构。如果是Master IRP的最后一个Associated IRPI/O管理器直接对IRP本身调用IoCompleteRequest()函数。

//

// Check to see whether this is an associated IRP. If so, then decrement

// the count in the master IRP. If the count is decremented to zero,

// then complete the master packet as well.

//

 


本文地址:http://www.45fan.com/dnjc/72122.html
Tags: windows FileSystem Internals
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部