图5-1显示了IRP的数据结构,阴影部分代表不透明域。下面是该结构中重要域的简要描述。

MdlAddress(PMDL)域指向一个内存描述符表(MDL),该表描述了一个
与该请求关联的用户模式缓冲区。如果顶级设备对象的Flags域为DO_DIRECT_IO,则I/O管理器为IRP_MJ_READ或
IRP_MJ_WRITE请求创建这个MDL。如果一个IRP_MJ_DEVICE_CONTROL请求的控制代码指定METHOD_IN_DIRECT
或METHOD_OUT_DIRECT操作方式,则I/O管理器为该请求使用的输出缓冲区创建一个MDL。MDL本身用于描述用户模式虚拟缓冲区,但它同
时也含有该缓冲区锁定内存页的物理地址。为了访问用户模式缓冲区,驱动程序必须做一点额外工作。

图5-1.I/O请求包数据结构

Flags(ULONG)域包含一些对驱动程序只读的标志。但这些标志与WDM驱动程序无关。

AssociatedIrp(union)域是一个三指针联合。其中,与WDM驱动程序相关的指针是AssociatedIrp.SystemBuffer
SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中。对于IRP_MJ_READ和IRP_MJ_WRITE操作,如
果顶级设备指定DO_BUFFERED_IO标志,则I/O管理器就创建这个数据缓冲区。对于IRP_MJ_DEVICE_CONTROL操作,如果
I/O控制功能代码指出需要缓冲区(见第九章),则I/O管理器就创建这个数据缓冲区。I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲
区,这也是创建IRP过程的一部分。这些数据可以是与WriteFile调用有关的数据,或者是DeviceIoControl
用中所谓的输入数据。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。对于指定了
METHOD_BUFFERED的I/O控制操作,驱动程序把所谓的输出数据放到这个缓冲区,然后I/O管理器再把数据复制到用户模式的输出缓冲区。

IoStatus(IO_STATUS_BLOCK)是一个仅包含两个域的结构,驱动程序在最终完成请求时设置这个结构。IoStatus.Status域将收到一个NTSTATUS代码,而IoStatus.Information
类型为ULONG_PTR,它将收到一个信息值,该信息值的确切含义要取决于具体的IRP类型和请求完成的状态。Information域的一个公认用法
是用于保存数据传输操作,如IRP_MJ_READ,的流量总计。某些PnP请求把这个域作为指向另外一个结构的指针,这个结构通常包含查询请求的结果。

RequestorMode将等于一个枚举常量UserModeKernelMode,指定原始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。

PendingReturned(BOOLEAN)如果为TRUE,则表明处理该IRP的最低级派遣例程返回了STATUS_PENDING。完成例程通过参考该域来避免自己与派遣例程间的潜在竞争。

Cancel(BOOLEAN)如果为TRUE,则表明IoCancelIrp已被调用,该函数用于取消这个请求。如果为FALSE,则表明没有调用IoCancelIrp函数。取消IRP是一个相对复杂的主题,我将在本章的最后详细描述它。

CancelIrql(KIRQL)是一个IRQL值,表明那个专用的取消自旋锁是在这个IRQL上获取的。当你在取消例程中释放自旋锁时应参考这个域。

CancelRoutine(PDRIVER_CANCEL)是驱动程序取消例程的地址。你应该使用IoSetCancelRoutine函数设置这个域而不是直接修改该域。

UserBuffer(PVOID)
对于METHOD_NEITHER方式的IRP_MJ_DEVICE_CONTROL请求,该域包含输出缓冲区的用户模式虚拟地址。该域还用于保存读写请
求缓冲区的用户模式虚拟地址,但指定了DO_BUFFERED_IO或DO_DIRECT_IO标志的驱动程序,其读写例程通常不需要访问这个域。当处理
一个METHOD_NEITHER控制操作时,驱动程序能用这个地址创建自己的MDL。

Tail.OverlayTail联合中的一种结构,它含有几个对WDM驱动程序有潜在用途的成员。图5-2是Tail联合的组成图。在这个图中,以水平方向从左到右是这个联合的三个可选成员,在垂直方向是每个结构的成员描述。Tail.Overlay.DeviceQueueEntry(KDEVICE_QUEUE_ENTRY)和Tail.Overlay.DriverContext(PVOID[4])是Tail.Overlayare内一个未命名联合的两个可选成员(只能出现一个)。I/O管理器把DeviceQueueEntry作为设备标准请求队列中的连接域。当IRP还没有进入某个队列时,如果你拥有这个IRP你可以使用这个域,你可以任意使用DriverContext中的四个指针。Tail.Overlay.ListEntry(LIST_ENTRY)仅能作为你自己实现的私有队列的连接域。

图5-2.IRP中Tail联合的组成图

CurrentLocation(CHAR)和Tail.Overlay.CurrentStackLocation(PIO_STACK_LOCATION)没有公开为驱动程序使用,因为你完全可以使用象IoGetCurrentIrpStackLocation这样的函数获取这些信息。但意识到CurrentLocation就是当前I/O堆栈单元的索引以及CurrentStackLocation就是指向它的指针,会对驱动程序调试有一些帮助。

  I/O堆栈 
  任何内核模式程序在创建一个IRP时,同时还创建了一个与之关联的 IO_STACK_LOCATION结构数组:数组中的每个堆栈单元都对应一个将处理该IRP的驱动程序,另外还有一个堆栈单元供IRP的创建者使用(见图5-3)。堆栈单元中包含该IRP的类型代码和参数信息以及完成函数的地址。图5-4显示了堆栈单元的结构。 
   
   
   
  图5-3.驱动程序和I/O堆栈之间的平行关系 
  注意 
  我将在本章稍后处讨论IRP的创建机制。将帮助你了解DEVICE_OBJECT的StackSize域,该域指出IRP应为其目标设备驱动程序保留多少堆栈单元。 
   
   
   
  图5-4.I/O堆栈单元数据结构 
  MajorFunction(UCHAR)是该IRP的主功能码。这个代码应该为类似 IRP_MJ_READ一样的值,并与驱动程序对象中MajorFunction表的某个派遣函数指针相对应。如果该代码存在于某个特殊驱动程序的I/O堆栈单元中,它有可能一开始是,例如IRP_MJ_READ,而后被驱动程序转换成其它代码,并沿着驱动程序堆栈发送到低层驱动程序。我将在第十一章(USB总线)中举一个这样的例子,USB驱动程序把标准的读或写请求转换成内部控制操作,以便向USB总线驱动程序提交请求。 
  MinorFunction(UCHAR)是该IRP的副功能码。它进一步指出该IRP属于哪个主功能类。例如,IRP_MJ_PNP请求就有约一打的副功能码,如IRP_MN_START_DEVICE、IRP_MN_REMOVE_DEVICE,等等。 
  Parameters(union)是几个子结构的联合,每个请求类型都有自己专用的参数,而每个子结构就是一种参数。这些子结构包括Create(IRP_MJ_CREATE请求)、Read(IRP_MJ_READ请求)、StartDevice(IRP_MJ_PNP的IRP_MN_START_DEVICE子类型),等等。 
  DeviceObject(PDEVICE_OBJECT)是与该堆栈单元对应的设备对象的地址。该域由IoCallDriver函数负责填写。 
  FileObject(PFILE_OBJECT)是内核文件对象的地址,IRP的目标就是这个文件对象。驱动程序通常在处理清除请求(IRP_MJ_CLEANUP)时使用FileObject指针,以区分队列中与该文件对象无关的IRP。 
  CompletionRoutine(PIO_COMPLETION_ROUTINE)是一个I/O完成例程的地址,该地址是由与这个堆栈单元对应的驱动程序的更上一层驱动程序设置的。你绝对不要直接设置这个域,应该调用IoSetCompletionRoutine函数,该函数知道如何参考下一层驱动程序的堆栈单元。设备堆栈的最低一级驱动程序并不需要完成例程,因为它们必须直接完成请求。然而,请求的发起者有时确实需要一个完成例程,但通常没有自己的堆栈单元。这就是为什么每一级驱动程序都使用下一级驱动程序的堆栈单元保存自己完成例程指针的原因。 
  Context(PVOID)是一个任意的与上下文相关的值,将作为参数传递给完成例程。你绝对不要直接设置该域;它由IoSetCompletionRoutine函数自动设置,其值来自该函数的某个参数。 
  The IRP structure is a partial opaque structure that represents an I/O request packet. Drivers can use the following members of the IRP structure. 
  typedef struct _IRP { 
  . 
  . 
  PMDL MdlAddress; 
  ULONG Flags; 
  union { 
  struct _IRP *MasterIrp; 
  . 
  . 
  PVOID SystemBuffer; 
  } AssociatedIrp; 
  . 
  . 
  IO_STATUS_BLOCK IoStatus; 
  KPROCESSOR_MODE RequestorMode; 
  BOOLEAN PendingReturned; 
  . 
  . 
  BOOLEAN Cancel; 
  KIRQL CancelIrql; 
  . 
  . 
  PDRIVER_CANCEL CancelRoutine; 
  PVOID UserBuffer; 
  union { 
  struct { 
  . 
  . 
  union { 
  KDEVICE_QUEUE_ENTRY DeviceQueueEntry; 
  struct { 
  PVOID DriverContext[4]; 
  }; 
  }; 
  . 
  . 
  PETHREAD Thread; 
  . 
  . 
  LIST_ENTRY ListEntry; 
  . 
  . 
  } Overlay; 
  . 
  . 
  } Tail; 
  } IRP, *PIRP; 
  Members 
  MdlAddress 
  Pointer to an MDL describing a user buffer, if the driver is using direct I/O, and the IRP major function code is one of the following: 
  IRP_MJ_READ 
  The MDL describes an empty buffer that the device or driver fills in. 
  IRP_MJ_WRITE 
  The MDL describes a buffer that contains data for the device or driver. 
  IRP_MJ_DEVICE_CONTROLor IRP_MJ_INTERNAL_DEVICE_CONTROL 
  If the IOCTL code specifies the METHOD_IN_DIRECT transfer type, the MDL describes a buffer that contains data for the device or driver. 
  If the IOCTL code specifies the METHOD_OUT_DIRECT transfer type, the MDL describes an empty buffer that the device or driver fills in. 
  For more information about the buffers that are associated with METHOD_IN_DIRECT and METHOD_OUT_DIRECT transfer types in IOCTL codes, see Buffer Descriptions for I/O Control Codes. 
  If the driver is not using direct I/O, this pointer is NULL. 
  Flags 
  File system drivers use this field, which is read-only for all drivers. Network and, possibly, highest-level device drivers also might read this field, which can be set with one or more of the following system-defined masks: 
  IRP_NOCACHE 
  IRP_PAGING_IO 
  IRP_MOUNT_COMPLETION 
  IRP_SYNCHRONOUS_API 
  IRP_ASSOCIATED_IRP 
  IRP_BUFFERED_IO 
  IRP_DEALLOCATE_BUFFER 
  IRP_INPUT_OPERATION 
  IRP_SYNCHRONOUS_PAGING_IO 
  IRP_CREATE_OPERATION 
  IRP_READ_OPERATION 
  IRP_WRITE_OPERATION 
  IRP_CLOSE_OPERATION 
  IRP_DEFER_IO_COMPLETION 
  AssociatedIrp.MasterIrp 
  Pointer to the master IRP in an IRP that was created by a highest-level driver's call to IoMakeAssociatedIrp.
  AssociatedIrp.SystemBuffer 
  Pointer to a system-space buffer. 
  If the driver is using buffered I/O, the buffer's purpose is determined by the IRP major function code, as follows: 
  IRP_MJ_READ 
  The buffer receives data from the device or driver. The buffer's length is specified byParameters.Read.Lengthin the driver's IO_STACK_LOCATIONstructure. 
  IRP_MJ_WRITE 
  The buffer supplies data for the device or driver. The buffer's length is specified byParameters.Write.Lengthin the driver's IO_STACK_LOCATION structure. 
  IRP_MJ_DEVICE_CONTROLor IRP_MJ_INTERNAL_DEVICE_CONTROL 
  The buffer represents both the input and output buffers that are supplied to DeviceIoControlandIoBuildDeviceIoControlRequest. Output data overwrites input data. 
  For input, the buffer's length is specified by Parameters.DeviceIoControl.InputBufferLengthin the driver's IO_STACK_LOCATION structure. 
  For output, the buffer's length is specified by Parameters.DeviceIoControl.OutputBufferLengthin the driver's IO_STACK_LOCATION structure. 
  For more information, see Buffer Descriptions for I/O Control Codes. 
  If the driver is using direct I/O, the buffer's purpose is determined by the IRP major function code, as follows: 
  IRP_MJ_READ 
  NULL. 
  IRP_MJ_WRITE 
  NULL. 
  IRP_MJ_DEVICE_CONTROLor IRP_MJ_INTERNAL_DEVICE_CONTROL 
  The buffer represents the input buffer that is supplied to DeviceIoControlandIoBuildDeviceIoControlRequest. 
  The buffer's length is specified by Parameters.DeviceIoControl.InputBufferLengthin the driver's IO_STACK_LOCATION structure. 
  For more information, see Buffer Descriptions for I/O Control Codes. 
  IoStatus 
  Contains the IO_STATUS_BLOCKstructure in which a driver stores status and information before calling IoCompleteRequest. 
  RequestorMode 
  Indicates the execution mode of the original requester of the operation, one of UserModeor KernelMode. 
  PendingReturned 
  If set to TRUE, a driver has marked the IRP pending. Each IoCompletionroutine should check the value of this flag. If the flag is TRUE, and if the IoCompletionroutine will not return STATUS_MORE_PROCESSING_REQUIRED, the routine should call IoMarkIrpPendingto propagate the pending status to drivers above it in the device stack. 
  Cancel 
  If set to TRUE, the IRP either is or should be canceled. 
  CancelIrql 
  Contains the IRQL at which a driver is running when IoAcquireCancelSpinLockis called. 
  CancelRoutine 
  Contains the entry point for a driver-supplied Cancelroutine to be called if the IRP is canceled. NULL indicates that the IRP is not currently cancelable. 
  UserBuffer 
  Contains the address of an output buffer if the major function code in the I/O stack location is IRP_MJ_DEVICE_CONTROLor IRP_MJ_INTERNAL_DEVICE_CONTROLand the I/O control code was defined with METHOD_NEITHER. 
  Tail.Overlay.DeviceQueueEntry 
  If IRPs are queued in the device queue associated with the driver's device object, this field links IRPs in the device queue. These links can be used only while the driver is processing the IRP. 
  Tail.Overlay.DriverContext 
  If IRPs are not queued in the device queue associated with the driver's device object, this field can be used by the driver to store up to four pointers. This field can be used only while the driver owns the IRP. 
  Tail.Overlay.Thread 
  Is a pointer to the caller's thread control block. Higher-level drivers that allocate IRPs for lower-level removable-media drivers must set this field in the IRPs they allocate. Otherwise, the FSD cannot determine which thread to notify if the underlying device driver indicates that the media requires verification. 
  Tail.Overlay.ListEntry 
  If a driver manages its own internal queues of IRPs, it uses this field to link one IRP to the next. These links can be used only while the driver is holding the IRP in its queue or is processing the IRP. 
  Headers 
  Defined in wdm.hand ntddk.h. Include wdm.hor ntddk.h. 
  Comments 
  Undocumented members of the IRP structure are reserved, used only by the I/O manager or, in some cases, by FSDs. 
  An IRP is the basic I/O manager structure used to communicate with drivers and to allow drivers to communicate with each other. A packet consists of two different parts: 
  Header, or fixed part of the packet? This is used by the I/O manager to store information about the original request, such as the caller's device-independent parameters, the address of the device object upon which a file is open, and so on. It is also used by drivers to store information such as the final status of the request. 
  I/O stack locations? Following the header is a set of I/O stack locations, one per driver in the chain of layered drivers for which the request is bound. Each stack location contains the parameters, function codes, and context used by the corresponding driver to determine what it is supposed to be doing. For more information, see the IO_STACK_LOCATIONstructure. 
  While a higher-level driver might check the value of the CancelBoolean in an IRP, that driver cannot assume the IRP will be completed with STATUS_CANCELLED by a lower-level driver even if the value is TRUE. 
  See AlsoIoCreateDevice, IoGetCurrentIrpStackLocation, IoGetNextIrpStackLocation, IoSetCancelRoutine, IoSetNextIrpStackLocation, IO_STACK_LOCATION, IO_STATUS_BLOCK

IRP和IO_STACK_LOCATION结构相关推荐

  1. windows内核开发学习笔记十七:IRP 和 IO_STACK_LOCATION 的交互

    windows内核开发学习笔记十七:IRP 和 IO_STACK_LOCATION 的交互 前面两篇学习笔记分别介绍了IRP和IO_STACK_LOCATION,整个设备栈来处理这个IRP,但是每个设 ...

  2. IRP和IO_STACK_LOCATION

    当一个应用程序调用函数去操作某个设备时,比如调用createFile,deviceIOControl,等等时,I/O管理器为此函数创建一个IRP数据结构对象和一个IRP_STACK_LOCATION数 ...

  3. Windows驱动之IRP结构

    文章目录 Windows驱动之IRP结构 1. IRP 2. IO_STACK_LOCATION 3. IRP 和 IO_STACK_LOCATION 的交互 3.1 IoAllocateIrp 3. ...

  4. 《寒江独钓》内核学习笔记(1)-- IRP - .Little Hann

     原文  http://www.cnblogs.com/LittleHann/p/3450436.html 在学习内核过滤驱动的过程中,遇到了大量的涉及IRP操作的代码,这里有必要对IRP的数据结 ...

  5. 从源码角度浅谈IRP

    从源码角度看IRP的构建 一.前言 1.写作目的 2.参考资料 二.文件加解密中的IRP应用 1.概览 2.什么是IRP 3.StackSize.Attached.AttachedTo的分析 4.什么 ...

  6. IRP(I/O Request Package)详解

    篇一: 简介: IRP(I/O Request Package)在windows内核中,有一种系统组件--IRP,即输入输出请求包. 当上层应用程序需要访问底层输入输出设备时,发出I/O请求,系统会把 ...

  7. 驱动学习笔记 IRP

    在学习内核过滤驱动的过程中,遇到了大量的涉及IRP操作的代码,这里有必要对IRP的数据结构和与之相关的API函数做一下笔记. 1. 相关阅读资料 <深入解析 windows 操作系统(第4版,中 ...

  8. Windows IRP

    IRP(I/O Request Packet),是由IO manager发起的对device的IO请求. 当用户调用系统API,如createFile类似的函数,其实是会交给IO manager来做相 ...

  9. 内核文件管理-IRP(一)创建或打开文件

    内核下通过直接向 FSD (File System Driver) 发送 IRP (I/O Request Packet)来管理文件,可以绕过一些 API Hook. 本文讲怎样通过向 FSD 发送 ...

最新文章

  1. 2019年了,中文分词到底该怎么做?中文分词十年方法大盘点(附下载)
  2. Http和Https对比
  3. Syncd - 开源自动化部署工具
  4. 后台命名查询sql查某几个字段传到前台
  5. 现代软件工程 来自卓越大学教师的建议 (读书笔记)
  6. 2、使用Spring框架能带来哪些好处
  7. Unity超基础学习笔记(三)
  8. 机试题:地图定位、拍照并显示、录制视频并播放
  9. 70. Climbing Stairs【leetcode】递归,动态规划,java,算法
  10. python考试题目及答案-这就是你需要的python99道练习题(附答案)
  11. iOS 去掉UISearchBar输入框上面的黑线
  12. linux内核配置成qspi挂载,【分享】在Linux/U-Boot里为QSPI Flash使用UBIFS
  13. 【apicloud问题解决记录】键盘弹出监听处理以及头部底部的黑色闪屏现象
  14. WTK6900H语音识别单芯片实现智能语音识别蓝牙耳机方案设计
  15. 石英晶体振荡器的检定方法
  16. OpenCV黑魔法之隐身衣 | 附源码
  17. 基于Android的万豪酒店APP设计与实现
  18. 状态机(FSM)的分类描述
  19. DRAM(动态随机储存器)的内部工作原理简述
  20. 淘宝店群月入万元,店群20大常见方法都在这

热门文章

  1. C++之编码问题(Unicode,ASCII,本地默认)
  2. 解决WINCE500中INTEL编译器无法完全卸载的问题
  3. SQL Server 创建约束图解 唯一 主键
  4. Codeforces 768E:Game of Stones
  5. 用Perl发送邮件小例子
  6. What is 软件工程
  7. sqoop配置与使用
  8. App Store 状态列表
  9. Sharepoint学习笔记 –架构系列—Sharepoint的客户端对象模型(Client Object Model)
  10. 财会小白的办公室自救指南