reactos:reactos操作系统实现(88)来源: 发布时间:星期一, 2009年9月28日 浏览:0次 评论:0
IRP 是 I/O request packet 缩写即 I/O 请求包驱动和驱动的间通过 IRP 进行通信而使用驱动应用层 CreatFile,ReadFile,WriteFile,DeviceIoControl 等说到底也是使用 IRP 和驱动进行通信
个 IRP 由两部分组成首先是头部或者叫包固定部分是个 IRP 结构紧跟在这个头部的后是 I/O栈位置这是个 IO_STACK_LOCATION 结构这个中元素个数是根据情况而定由 IoAllocateIrp( IN CCHAR StackSize , IN BOOLEAN ChargeQuota ) 时参数 StackSize 决定而 StackSize 通常由 IRP 发往目标 DEVICE_OBJECT StackSize 决定而这个 StackSize 是由设备对象连入所在设备栈时根据在设备栈中位置决定我们先看看 IRP 结构和 IO_STACK_LOCATION 结构定义实现代码如下: #001 typedef struct _IRP { 标志IRP类型 #002 CSHORT Type; 本IRP长度和IRP栈长度 #003 USHORT Size; 指向内存描述符列表 #004 struct _MDL *MdlAddress; IRP包特征标志比如直接I/O还是缓存CacheI/O等等 #005 ULONG Flags; 保存驱动相关数据结构其中和WDM驱动相关指针是AssociatedIrp.Buffer Buffer指针指向个数据缓冲区该缓冲区位于内核模式非分页内存中对于IRP_MJ_READ和IRP_MJ_WRITE操作如果顶级设备指定DO_BUFFERED_IO标志则I/O管理器就创建这个数据缓冲区对于IRP_MJ_DEVICE_CONTROL操作如果I/O控制功能代码指出需要缓冲区(见第 9章)则I/O管理器就创建这个数据缓冲区I/O管理器把用户模式发送给驱动数据复制到这个缓冲区这也是创建IRP过程部分这些数据可以是和WriteFile有关数据或者是DeviceIoControl中所谓输入数据对于读请求设备驱动把读出数据填到这个缓冲区然后I/O管理器再把缓冲区内容复制到用户模式缓冲区对于指定了METHOD_BUFFEREDI/O控制操作驱动把所谓输出数据放到这个缓冲区然后I/O管理器再把数据复制到用户模式输出缓冲区 #006 union { 当前线程入口 #011 LIST_ENTRY ThreadListEntry; 个仅包含两个域结构驱动在最终完成请求时设置这个结构 #012 IO_STATUS_BLOCK IoStatus; 等于个枚举常量UserMode或KernelMode指定原始I/O请求来源驱动有时需要查看这个值来决定是否要信任某些参数 #013 KPROCESSOR_MODE RequestorMode; IRP是否被阻塞 #014 BOOLEAN PendingReturned; IRP栈大小 #015 CHAR StackCount; 当前栈位置 #016 CHAR CurrentLocation; IRP是否被取消操作 #017 BOOLEAN Cancel; 当IoAcquireCancelSpinLock指明它是那个IRQ级别 #018 KIRQL CancelIrql; APC环境索引 #019 CCHAR ApcEnvironment; 内存分配方式比如定额地增加还是固定大小等等 #020 UCHAR AllocationFlags; 保存用户I/O状态 #021 PIO_STATUS_BLOCK UserIosb; 保存用户事件 #022 PKEVENT UserEvent; APC、或分配内存大小 #023 union { 驱动取消例程地址 #030 volatile PDRIVER_CANCEL CancelRoutine; 指向用户缓冲区 #031 PVOID UserBuffer; 设备队列入口或者设备上下环境指针 #033 struct { 批向内核线程 #040 PETHREAD Thread; 辅助缓冲区 #041 PCHAR AuxiliaryBuffer; I/O栈位置 #042 _ANONYMOUS_STRUCT struct { 原来文件对象 #049 struct _FILE_OBJECT *OriginalFileObject; APC队列 #051 KAPC Apc; I/O完成设置用户关键数据 #052 PVOID CompletionKey; 上面学习了IRP结构知道了IRP保存基本内容也就是说知道了有什么相关东西这就相当有了原材料那么如何样加工和处理这些原材料呢?那就得去分析IRP相关操作也就是IRP相关算法下面就从IRP分配开始实现代码如下: #001 PIRP 计算IRP占用大小包括IRP头部和IRP栈空间 #007 USHORT Size = IoSizeOfIrp(StackSize); 如果设置为定额分配方式就添加这个标志位 #013 /* Set Charge Quota Flag */ 设置为固定分配大小空间 #021 /* Set Fixed Size Flag */ 需要使用个大列表方式 #024 /* See we should use big list */ 获取当前处理器控制块 #031 /* Get the PRCB */ 获取后备列表 #034 /* Get the P List First */ 从后备列表里分配个IRP包 #037 /* Attempt allocation */ 如果没有从后备列表里分配到IRP就需要从内存里分配 #054 /* Check we have to use the pool */ 从后备列表里分配失败 #057 /* Did we try lookaside and fail? */ 定额增加分配方式 #060 /* Check we should charge quota */ 非定额增加分配方式 #069 /* Allocate the IRP With no Quota charge */ 现在化IRP些属性 #082 /* Now Initialize it */ 设置IRP分配标志 #085 /* Set the Allocation Flags */ 返回分配成功IRP包 #088 /* Return it */ 0
相关文章读者评论发表评论 |
|