IRP数据结构

来源:互联网 发布:滇红58淘宝 编辑:程序博客网 时间:2024/06/10 09:16

几乎所有的Windows2000的I/O都是包驱动的,系统采取一种称为“I/O请求包(IRP--­I/O request packet)”的数据结构来完成与内核模式驱动程序通信。IRP由I/O管理器根据用户态程序提出的请求创建并传给相应的驱动程序。在分层的驱动程序中,这个过程很复杂,一个IRP常常要穿越几层驱动程序。另外,驱动程序也能够建立新的IRP并传递给其它驱动程序。

 

IRP功能的复杂性决定了它结构的复杂性,正确的理解IRP的结构是理解WDM框架的基础。IRP由I/O管理器在非分页内存池内创建,它包括两部分:头部区域和I/O堆栈位置

 

IRP头部可见字段

 

AssociatedIrp.SystemBuffer      设备执行缓冲I/O时,指向系统空间缓冲区

 

PMDL MdlAddress                    设备执行直接I/O时,指向用户空间的内存描述表

 

IO_STATUS_BLOCK IoStatus   包含了I/O请求的状态;驱动程序在最终完成请求时设置这个结构。IoStatus.Status域将收到一个NTSTATUS代码。

 

PVOID UserBuffer                    对于METHOD_NEITHER方式的

 

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

 

BOOLEAN Cancel                     指示IRP已经被取消


I/O堆栈位置

 

MajorFunction                           指示执行什么I/O操作以及如何解释Parameters 字段

 

MinorFunction                           由文件系统合SCSI驱动程序使用

 

Parameters                               MajorFunction代码决定此联合的内容

 

DeviceObject                            I/O请求的目标设备

 

FileObject                                 请求的文件对象


       I/O堆栈位置的主要目的是,保存一个I/O请求的函数代码和参数。而I/O堆栈数量实际上就是参与I/O请求的I/O层的数量。在一个IRP中,上层驱动负责为下层驱动设置堆栈位置指针。驱动程序可以为每个IRP调用IoGetCurrentIrpStackLocation来获得指向其自身堆栈位置的指针,而上层驱动程序必须调用IoGetNextIrpStackLocation来获得指向下层驱动程序堆栈位置的指针。因此,上层驱动可以在传送IRP给下层驱动之前设置堆栈位置的内容。

 

       上层驱动调用IoCallDriver,将DeviceObject成员设置成下层驱动目标设备对象。当上层驱动完成IRP时,IoCompletion 函数被调用,I/O管理器传送给IoCompletion函数一个指向上层驱动的设备对象的指针。


引自:  http://blog.csdn.net/hazy/archive/2005/09/15/481631.aspx

 


 

在微软的Windows 操作系统家族中,都通过发送I/O 请求包(IRP, I/o Request Packets)来进行和驱动程序的通讯。

IRP 可以被定义:
(1)一个被放置I/O请求的容器
      IRP 设计来可以被异步操作
      IRP 可以被在完成前取消
      IRP 设计来适合于需要多驱动协同完成的输入输出操作

      IRP 数据结构封装了一个被请求的驱动所需要的,用来回复这一请求的[全部]信息。而请求则可能来自于用户模式或者内核模式。   

      IRP的组成:
      一个用来描述主要I/O 请求的头部
      一组用来描述下级请求(有时就被称作子请求,sub-requests)的参数

      IO_STACK_LOCATION 结构:
     对于特定IRP 的主要以及次要的方法代码
   针对这些代码的参数
   一个指向相应驱动的设备对象(device object)的指针
   一个指向IoCompletion 例程的指针,如果驱动有过设定
   一个指向和这一请求相关联的文件对象的指针
   一些可变标志以及上下文[关联]区域

      
(2)一个与线程无关的调用栈

      将IRP 传递到下一级的驱动程序。当驱动转发一个IRP,它(驱动程序)必须向IRP 参数组增加下一个I/O 栈位置,告知这一IRP栈的指针,然后调用下一驱动的分发例程(dispatch routine)。基本说来,就是驱动向下调用IRP 栈(calling down the IRP stack)。

      在驱动程序将IRP 传递个下一个驱动之后,就不再拥有这个IRP。

一个文件对象的生命周期
       每当一个设备被打开,一个文件对象就被建立了。当IO 管理器创建并打开一个文件对象,它同时创建一个指向(refer)这一对象的句柄。IRP_MJ_CREATE、IRP_MJ_CLEANUP 以及IRP_MJ_CLOSE 请求定义了一个文件对象的生命周期。


     IRP_MJ_CREATE 请求:
     一个IRP_MJ_CREATE 请求告知特定的驱动:一个新的文件对象被创建出来了。IO 管理器典型的做法(通常)是在用户模式的应用程序调用CreateFile 函数或者内核模式驱动调用ZwCreateFile 例程时发送出一个IRP_MJ_CREATE 请求。
   在一个IRP_MJ_CREATE 请求中,当前IO 栈位置包含了一个FileObject 结构,用以标示(identify)要被打开的文件对象。这个FileObject 结构列明了:
   要打开的文件的名称,在FileObject->FileName 
   两个提供给驱动程序使用的指针,在FileObject->FsContext 以及FileObject->FsContext2 域


   IRP_MJ_CLEANUP 请求


     一个IRP_MJ_CLEANUP 请求通告驱动程序:一个文件对象的上个(last)的句柄被关闭了。并不表示那个文件对象已经被删除了。

    IRP_MJ_CLOSE 请求

   一个IRP_MJ_CLOSE 请求通告驱动程序:一个文件对象被删除了。
   IO 管理器在以下两种情况都为真时,为相应的文件对象发送IRP_MJ_CLOSE 请求:
   文件对象所有的句柄都被关闭了
   没有显著的联系(参考,reference)指向这一对象

数据传输的机制
Windows 操作系统家族支持三种数据传输机制:
(通过修改DeviceObject->Flags 域的值来指定支持那一种传输机制)
(1)缓存IO(Buffered I/O)在内核模式上操作对用户数据的拷贝
     DeviceObject->Flags = DO_BUFFERED_IO

(2)直接IO(Direct I/O)通过内存描述元列表(MDL, Memory Descriptor List)以及内核模式的指针直接访问用户数据
     DeviceObject->Flags = DO_DIRECT_IO

(3)非上述方法IO(Method neither I/O,既非缓存,也非直接IO)通过用户模式的指针访问用户数据


输入、输出控制码(IOCTLs, I/O Control Codes)

IO 管理器将一个IO 控制码(IOCTL)作为IRP 的部分将请求发送出去,而不同于读、写的请求。一个IOCTL 是一个32 位的控制码,用来标识一个IO 或设备操作。对那些特定IOCTL的请会同时有输入和输出的缓冲区。
操作系统支持两种类型的IOCTL,它们被放在两样不同的IRP 中发送:
(1) IRP_MJ_DEVICE_CONTROL 请求,能够被从用户模式或者内核模式发出。这些请求有时候被称作公共IOCTL(public IOCTLs)
(2) IRP_MJ_INTERNAL_DEVICE_CONTROL 请求,只能够由内核模式的组件发出。
这些请求典型的用途是驱动到驱动的通讯,有时被称作私有IOCTL(private IOCTLs)

 

引自:  http://hi.baidu.com/cg_jane/blog/item/156420458fd32b45510ffee9.html

原创粉丝点击