文章作者:grayfox
作者主页:http://nokyo.blogbus.com
原始出处:http://www.blogbus.com/nokyo-logs/34010655.html

这一节会对IRP进行稍微详细的讲解,这是在看了王艳平的《Windows网络与通信程序设计》之后理解的。
      在Windows中几乎所有的I/O都是通过包(packet)驱动的,每个单独的I/O由一个工作命令描述,此命令将会告诉驱动程序需要一些什么操作,并通过I/O子系统跟踪处理过程。这些工作命令就表现为一个个被称为IRP的数据结构。
      IRP是从未分页内存申请的大小可变的结构,它由两部分组成:
      1,包含一般簿记信息的头区域,即IRP头。
      2,若干个成为I/O堆栈位置的内存块,即I/O堆栈。

IRP头部是一个固定长度的结构,它包含了关于整个I/O请求的各种信息。其中的一部分信息可以通过驱动程序访问,另一部分仅供I/O管理器使用,下面列出了允许驱动程序访问的域:

I/O_STATUS_BLOCK    I/OStatus;          // 包含I/O请求的状态
PVOID    AssociatedIrp.SystemBuffer;    // 指向系统缓冲区空间(使用缓冲区I/O)
PMDL    MdlAddress;         // 指向用户缓冲区空间的内核描述表(使用直接I/O)
PVOID    UserBuffer;         // I/O缓冲区的用户空间地址
BOOLEAN    Cancel;          // 指明此IRP已经被取消

I/OStatus的成员包含I/O操作的最终状态,当驱动程序将要完成IRP处理时,它将IRP的Status状态域设置为STATUS_XXX,同时应该将它的InformatI/On域设为0(如果有错误发生)或者一个功能代码指定的值(例如传输的字节数)。

紧跟在IRP头部之后的是I/O堆栈,这是一个I/O_STACK_LOCATI/ON结构的数组,这个数组中元素的个数是根据不同的实际情况而定的。
      I/O堆栈的主要目的是保存功能代码和I/O请求的参数,至于MajorFunctI/On域的作用就不用废话了,Parameters这个联合体需要根据不同情况作出不同的解释,它有Read、Write、DeviceI/OControl三种可能的解释,分别对应三个Win32 API函数,下面列出了I/O堆栈中一些常用的成员域:

UCHAR MajorFunctI/On;               // IRP_MJ_XXX功能代码
struct Read;                               // IRP_MJ_READ的参数
struct Write;                              // IRP_MJ_WRITE的参数
struct DeviceI/OControl;              // IRP_MJ_DEVICE_CONTROL的参数
PDEVICE_OBJECT DeviceObject;   // 该I/O请求的目标设备
PFILE_OBJECT FileObject;            // 该I/O请求的文件对象(如果有的话)

其中FileObject对应着用户模式下CreateFile函数创建的文件对象,FILE_OBJECT结构中的FsContext和FsContext2域是Per-Handle变量,即文件句柄唯一变量,驱动程序可在这里指定要为每个文件对象关联的数据。

Windows操作系统家族支持三种数据传输机制: 
      缓存 I/O(Buffered I/O)在内核模式上操作对用户数据的拷贝 
      直接 I/O(Direct I/O)通过内存描述元列表(MDL, Memory Descriptor List)以及内核模式的指针直接访问用户数据 
      其他方式 I/O(Method neither I/O,既非缓存,也非直接 I/O)通过用户模式的指针访问用户数据

对于标准的 I/O请求,例如IRP_MJ_READ和 IRP_MJ_WRITE,应该在驱动刚刚创建设备后,马上通过修改DeviceObject->Flags域的值来指定支持哪一种传输机制。

缓存 I/O 
 
      为了以缓存 I/O的方式接收读、写的请求,驱动会在初始化时在DeviceObject->Flags域上设置DO_BUFFERED_I/O标志。当驱动收到了一个缓存I/O 的请求,在特定的Irp->AssociatedIrp.SystemBuffer 域中会放有驱动应该操作的内核模式缓冲区的地址。 I/O 管理器,在进行读请求时将数据由内核模式缓冲区拷贝到用户模式缓冲区,或者在进行写请求时从用户模式缓冲区向内核模式缓冲区拷贝数据。 
 
直接 I/O 
 
      为了以直接 I/O的方式接收读、写请求,驱动会在初始化时在DeviceObject->Flags域上设置DO_DIRECT_I/O标志。当驱动接收到一个直接 I/O请求,特定的Irp->MdlAddress域中会放有一个用来描述请求缓冲区的MDL的地址。这个MDL列出了缓冲区的虚拟地址和尺寸,连同相应缓冲区中的物理页表(physical pages)。I/O 管理器会在将请求发送给驱动之前锁定这些物理页,并在(请求)完成的过程中解锁。驱动千万不能使用 MDL中列举的用户模式缓冲区地址,而必须通过调用 MmGetSystemAddressForMdlSafe宏来得到一个内核模式的地址。 
 
其他方式 I/O 
 
      为了接收非缓存非直接 I/O 的方式的请求,驱动初始化时在 DeviceObject->Flags域上既不设置 DO_BUFFERED_I/O 标志,也不设置 DO_DIRECT_I/O 标志。当驱动接收到这样的请求,相应的 Irp->UserBuffer 域会放有附属于这个请求的数据地址。因为这个缓冲区在用户地址空间上,驱动程序必须在用之前使相应的地址合法化。驱动程序在 try/except块里调用ProbeForRead或者 ProbeForWrite函数来合法化特定的指针。驱动还必须完全在 try/except块里处理所有对这一缓冲区的访问。 
另外,驱动还必须在应用(manipulating)数据之前将它拷贝到池(the pool)或堆栈里一个安全的内核模式地址。将数据拷贝到内核模式缓冲区确保了用户模式的调用者不会在驱动已经合法化数据之后再修改它。

【驱动笔记10】再谈IRP的更多相关文章

  1. 【驱动笔记9】初探IRP

    文章作者:grayfox作者主页:http://nokyo.blogbus.com原始出处:http://www.blogbus.com/nokyo-logs/34005738.html 此前我们可能 ...

  2. IBatis.Net学习笔记六--再谈查询

    在IBatis.Net学习笔记五--常用的查询方式 中我提到了一些IBatis.Net中的查询,特别是配置文件的写法. 后来通过大家的讨论,特别是Anders Cui 的提醒,又发现了其他的多表查询的 ...

  3. Samsung_tiny4412(驱动笔记10)----mdev,bus,device,driver,platform

    /*********************************************************************************** * * mdev,bus,de ...

  4. C++ Primer 学习笔记_32_STL实践与分析(6) --再谈string类型(下)

    STL实践与分析 --再谈string类型(下) 四.string类型的查找操作 string类型提供了6种查找函数,每种函数以不同形式的find命名.这些操作所有返回string::size_typ ...

  5. C++ Primer 学习笔记_44_STL实践与分析(18)--再谈迭代器【下】

    STL实践与分析 --再谈迭代器[下] 三.反向迭代器[续:习题] //P355 习题11.19 int main() { vector<int> iVec; for (vector< ...

  6. C++ Primer 学习笔记_43_STL实践与分析(17)--再谈迭代器【中】

    STL实践与分析 --再谈迭代器[中] 二.iostream迭代[续] 3.ostream_iterator对象和ostream_iterator对象的使用 能够使用ostream_iterator对 ...

  7. 【转】 Pro Android学习笔记(四三):Fragment(8):再谈Transaction和管理器

    目录(?)[-] Transaction的一些操作 再谈FragmentManager 调用其他fragment的方法 唤起activity 唤起fragment和相互通信 一些其它 Transact ...

  8. [转载]再谈百度:KPI、无人机,以及一个必须给父母看的案例

    [转载]再谈百度:KPI.无人机,以及一个必须给父母看的案例 发表于 2016-03-15   |   0 Comments   |   阅读次数 33 原文: 再谈百度:KPI.无人机,以及一个必须 ...

  9. 再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结

    这篇是对angularJS的一些疑点回顾,是对目前angularJS开发的各种常见问题的整理汇总.如果对文中的题目全部了然于胸,觉得对整个angular框架应该掌握的七七八八了.希望志同道合的通知补充 ...

随机推荐

  1. word图片自动编号与引用(转)

    http://blog.csdn.net/hunauchenym/article/details/5915616 用Word时,可能会遇到文中使用了大量的图片的情况,这时,若采用手动为图片编号的方法, ...

  2. 转码:gcc在代码中禁止某些warning

    http://www.itye.org/archives/3125 gcc 禁止warning 熟悉windows编程的人都知道,禁止编译器输出某个warning,在代码中可以这样 #pragma w ...

  3. 2013级C++第14周(春)项目——多态性、虚函数和抽象类

    课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接 第一部分 阅读程序1.阅读.改动和执行关于交通 ...

  4. 【Python】在控制台输出不同颜色的文字

    今天调程序出了一个极为奇怪的问题,由于控制台输出挺多,就想把问题着重表示一下,具体即是在控制台输出红色文字. 于是在网上搜寻到了这篇:https://www.cnblogs.com/gongxr/p/ ...

  5. Office PPT如何切换到返回幻灯片

    1 如图所示,有"老师""同学""家人"三个板块,如果依次播放,将播放"老师1" "老师2" &qu ...

  6. ArcGIS中的查询

    最近身体不适,静下心来看了一下以前收集的电子书.下面是<ArcGIS地理信息系统教程_第5版>(李玉龙)第5章“查询”的读书笔记. 1.查询的常见应用: 选择感兴趣的要素:查找哪些要素满足 ...

  7. Openfire与XMPP协议

    关于xmpp协议可以参考:http://www.jabbercn.org 什么是OpenFire Openfire 采用Java开发,开源的实时协作(RTC)服务器基于XMPP(Jabber)协议. ...

  8. PD的CDM模型中的三种实体关系

    PD的CDM模型中的三种实体关系 本文摘自:http://www.cnblogs.com/syf/articles/2480580.html PD 正向工程使用说明:http://download.c ...

  9. Java面试处理高并发

    经过查资料,方案如下所示.   1 从最基础的地方做起,优化我们写的代码,减少必要的资源浪费.           a.避免频繁的使用new对象,对于整个应用只需要存在一个实例的类,我们可以使用单例模 ...

  10. Httpclient 4, error 302. How to redirect?

    http://stackoverflow.com/questions/3658721/httpclient-4-error-302-how-to-redirect DefaultHttpClient ...