IRP数据结构

2024-03-05 02:32
文章标签 数据结构 irp

本文主要是介绍IRP数据结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

      几乎所有的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

这篇关于IRP数据结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775039

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

Python 内置的一些数据结构

文章目录 1. 列表 (List)2. 元组 (Tuple)3. 字典 (Dictionary)4. 集合 (Set)5. 字符串 (String) Python 提供了几种内置的数据结构来存储和操作数据,每种都有其独特的特点和用途。下面是一些常用的数据结构及其简要说明: 1. 列表 (List) 列表是一种可变的有序集合,可以存放任意类型的数据。列表中的元素可以通过索

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

【数据结构入门】排序算法之交换排序与归并排序

前言         在前一篇博客,我们学习了排序算法中的插入排序和选择排序,接下来我们将继续探索交换排序与归并排序,这两个排序都是重头戏,让我们接着往下看。  一、交换排序 1.1 冒泡排序 冒泡排序是一种简单的排序算法。 1.1.1 基本思想 它的基本思想是通过相邻元素的比较和交换,让较大的元素逐渐向右移动,从而将最大的元素移动到最右边。 动画演示: 1.1.2 具体步

数据结构:线性表的顺序存储

文章目录 🍊自我介绍🍊线性表的顺序存储介绍概述例子 🍊顺序表的存储类型设计设计思路类型设计 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾” 和“内容共创官” ,现在我来为大家介绍一下有关物联网-嵌入

[数据结构]队列之顺序队列的类模板实现

队列是一种限定存取位置的线性表,允许插入的一端叫做队尾(rear),允许删除的一端叫做队首(front)。 队列具有FIFO的性质 队列的存储表示也有两种方式:基于数组的,基于列表的。基于数组的叫做顺序队列,基于列表的叫做链式队列。 一下是基于动态数组的顺序队列的模板类的实现。 顺序队列的抽象基类如下所示:只提供了接口和显式的默认构造函数和析构函数,在派生类中调用。 #i