"深入了解IRP的请求机制和数据结构——驱动开发必备知识"

需积分: 0 0 下载量 165 浏览量 更新于2024-01-09 收藏 88KB PDF 举报
P做为一个放置 I/O 请求的容器成为了可能: l IRP 作为一个完全看不见的对象 对于驱动程序的提供者来说,IRP 可以简单地被看作是一个 I/O 请求,“它”只有一个指针而没有实际内容,这个指针指向了请求所需的缓冲区。这个缓冲区可以是输入也可以是输出,它依赖于请求是否是读或写操作。 l IRP 基于请求的相关信息 在数据结构的内容中保持了有关请求的重要信息。这些信息包括了请求的类型,传递数据的起始地址,最大的传递字节数等。 l IRP 对于整个 I/O 操作流程的维护 当一个 I/O 请求被传递给一个驱动程序的时候,当请求在系统内核中的各种组成部分间被传递的时候,IRP 将被作为“客户端”把相关的状态信息保留,这些状态信息将被用来决定请求的操作方式。 过去的版本的 Windows 操作系统,定义的 IRP 结构体就像是底层驱动开发人员的接口文档一样:它在这里是被彻底描述和规定。所幸的是,在 Windows 2000 及 以上的版本中,WDK 让把 IRP 结构带来了些可适用的改变。 流中有三个或者五个部分构成IRP的组织。不同的定义来自不同的操作系统版本或者不同的文档来源。但是,这些部分的表现方式总是和下面的话一样的: l 根部 该部分保留了一些和 IRP 请求有关的全局信息,例如它的类型,现在应该如何传递和执行等等。 l 主体部 在该部分中描述IRP所请求的I/O操作的具体细节,是驱动程序能够执行相应I/O请求所需的所有数据。 l 尾部 被请求的I/O操作顺利完成后,该部分允许将结果或者相关的状态信息返回给I/O管理器。 对于最简单的 I/O 请求来讲,只有这三个部分。 一个 I/O 请求被传递、执行、完成的这一过程称为IRP执行。在这过程中,一个IRP是不变的:它是从I/O发起到操作完成一直不变的。这个执行过程可以划分为多个不同的步骤。在不同的程序阶段,执行是可以被挂起或者放弃的。 一个IRP请求的执行是被I/O管理器控制的,被装载、传递和完成。一个IRP请求的执行是“全栈的”,这意味着它被操作系统的一系列驱动按照一个栈方式的有序操作来执行。每个驱动在执行这一过程的一点点的时间里做一些修改,所有驱动的修改积淀在一起,形成最终执行结果。 那`到现在为止我们对于IRP可以给的信息就是它会如何表示要传递的I/O请求,我们可以简称这样的IRP为“请求IRP”。上面还提到了一个新的概念:“全栈维护”,这种方法使得IRP在传递的过程中保持一个驱动无关的环境,所以有必要去更具体的考虑IRP的第二种定义。 第二重定义:IRP是一个与线程无关的调用栈 这一次时候,我们更从一个略不同的视角去认识一下IRP。现在,我们不再是在考虑它作为一个执行还是要求。我们应该考虑IRP执行的上下文环境是驱动在停止一条线程前的全部堆栈。 在 IRP 完成前后可能经历的操作包括: l IRP 的处理程序开始工作 l I/O 管理器或 IRP 的调用者存活状态结束时 或者有了更好的解释,假设有一个应用程序发来一个 I/O 请求,例如说CreateFile。当 I/O 管理器收到这一请求后,它初始化并填写IRP的根部,然后调用Sending Routine的处理程序函数。然后IRP在传递到内核中一个或者多个驱动程序并相继处理后,结果被返回给I/O管理器进一步向发送者返回结果。现在,如果发送此IRP请求的线程终止了,那么就会导致发送此IRP的过程结束了。 对于驱动程序提供者来说,IRP请求是“高效的”,是不用考虑发送请求的线程的状态导致的任何假设。这也是IRP设计者的一个很巧妙的设计。这意味着驱动程序提供者们不需要去加一个线程同步机制来处理IRP的请求,同时还意味着由Sending Routine所调用的IRP处理程序函数不需要去担心发送请求的线程什么时候结束。 关于IRP的例程和问题的进一步的讨论参见 WDK 中最新的Windows驱动开发包。