IRP 处理流程

2023-10-28 02:38
文章标签 流程 处理 irp

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

本文通过打开一个文件对象为例子,描述了一个带有两个I/O stack location的IRP的详细处理过程。当然一个IRP可以有多个I/O stack location,具体个数取决于将要处理该请求的驱动的层数。下图详细描述了驱动程序是如何通过使用I/O支持例程(IoXxx routines)来处理IRP以此来实现对相应文件的读写操作。




1:I/O管理器调用文件系统驱动(FSD)并把包含了子系统读/写请求的IRP传递给该驱动。 FSD访问IRP中的I/O stack location, 从而决定应该执行什么操作。


2:通过单此或者多次调用例程(IoAllocateIrp)来分配附加的IRP,FSD就可以把原始的请求分成几个小的请求(对于设备驱动不只一个的情况)。这些附加的IRP中的I/O stack location区域将会被下一级的驱动填充成零返回给FSD,正因为如此,FSD可以重复使用原始的IRP, 而不是向前面所讲的那样执行分配额外的IRP,并在这些IRP中创建针对下一层驱动的I/O stack location 并传送给下一层驱动。


3:对每一个驱动分配的IRP,如前面所述,FSD将调用I/O支持例程来注册一个由FSD提供的完成例程;在完成例程中,FSD可以判定下级驱动是否满足该请求,并且当下级驱动成功完成该IRP时释放该IRP。I/O管理器将调用FSD提供的完成例程来判断分配给驱动的IRP是成功完成了,还是完成了但有错误,或者是被取消了。上层驱动负责释放该驱动自己为下层驱动分配并设置的IRP。I/O管理器负责示释放它本身分配的并且被驱动完成的IRP。接下来,为了建立传递给下层驱动执行的请求,FSD将调用I/O支持例程(IoGetNextIrpStackLocation)来访问下层驱动的I/O stack location。(本例中,下一层驱动就是最后一层驱动)最后,FSD调用例程(IoCallDriver)将IRP传递给下一层驱动。


4:当IRP传递到下层驱动时,该驱动检查它对应的I/O stack location以此来判断自己在目标设备上该执行何种操作(由IRP_MJ_XXX之类的功能代码决定)。在指定的I/O stack location中已经把相应的目标设备通过设备对象抽象表征出来并出传递给本层驱动程序了。最底层的驱动可以做如下假设:I/O管理器把IRP转发给驱动的入口点,该入口点里面,驱动已经定义好了各种IRP_MJ_XXX操作(本例中是IRP_MJ_READ或者IRP_MJ_WRITE),而且上层的驱动已经对该请求的参数的有效性进行了检查。
如果没有上层驱动,那么底层驱动就要为针对IRP_MJ_XXX操作的参数的有效性进行检查,如果有效, 驱动程序通常调用I/O 支持例程来通知I/O管理器该层设备是将IRP挂起了,还是将IRP移入队列里等待,还是直接将IRP转发给由其他驱动提供的访问目标设备的驱动应用例程(此例中是一个物理或者逻辑设备: 磁盘或者分区)。

5: I/O管理器先判断驱动程序是否在忙于处理其他IRP,如果忙,则将IRP移入队列,并返回。否则,I/O管理器将把IRP转发给驱动提供的例程,该例程将在它所在的设备层发起I/O操作。

6:当设备中断发生时,驱动的中断服务例程(ISR)必须屏蔽相应中断并保存相关的上下文环境。然后,ISR将调用I/O支持例程(IoRequestDpc)将该IRP传递给由本层驱动提供的延时处理调用(DPC)例程中,以此使得该操作请求在比ISR低一级的硬件优先级下完成。

7:当驱动程序的DPC执行时,它使用上下文(由ISR中调用IoRequestDpc时传递下来)来完成I/O操作。 DPC调用相关的例程将下一个IRP(如果有的话)移出队列并将该IRP转发给由驱动提供的例程,这个例程开始在这个设备执行I/O操作。然后,DPC设置IRP中的I/O状态并调用例程IoCompleteRequest将它返回给I/O管理器。

8:I/O管理器把最底层的驱动程序的I/O stack location置零,然后调用文件系统已经注册好的完成例程(见步骤3)并把分配给FSD的IRP传递给文件系统驱动。该完成例程根据I/O状态(I/O status block)的结果来决定是重发该请求,还是更新原始请求保存的的内部状态信息,或者是释放分配给驱动的IRP。文件系统收集完所有分配给驱动的IRP中的状态信息,由此可以设置I/O的状态信息并结束原始IRP,当文件系统完成原始的IRP时,I/O管理器返回一个NTSTATUS的值给发起该I/O操作的原始请求者(子系统的原生函数)。


和上图描述的文件系统驱动一样,任何一个添加进驱动链表的新的驱动程序都可以实现下列功能:

●     在IRP中设置自己的完成例程。IoCompletion例程检查I/O status block来判断该IRP是被下一层的驱动成功完成了,还是被取消了, 或者是完成了但有错误. 完成例程还可以更新任何由驱动程序保存的IRP相关的状态, 也可以释放由驱动分配的任何操作相关的资源。另外,结束IRP之前,完成例程还可以延迟IRP的完成(通过告诉I/O管理器该IRP需要处理更多东西),并且可以在允许该IRP完成之前,向下一层驱动程序发送另外的请求。

●     在分配的IRP中可以创建下一层驱动对应的I/O stack location,并将请求发送给下一层驱动。

●     任何收到的IRP都可以通过在每一个IRP中添加针对下一层驱动的I/O stack location并调用IoCallDriver例程实现转发(值得注意的是: 针对主要功能代码为IRP_MJ_POWER,的IRP,驱动必须调用PoCallDriver例程才能转发)。

 

从上图我们可以知道,大部分驱动处理IRP是通过驱动提供的一组标准例程,但是处在驱动链中不同层的驱动必须有不同标准的例程。比如说,只有最底层的驱动可以处理来自物理设备的中断,所以只有最底层的驱动可以有ISR和DPC,ISR和DPC负责完成那些由中断驱动的I/O操作。从另一方面来说,因为最底层的驱动在收到来自设备的中断时就知道这些I/O操作已经完成,所以只有高层的驱动才有一个或者多个类似上文中提到的FSD的完成例程。


注:该文章英文原文出自msdn。



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



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

相关文章

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

Python自动化处理PDF文档的操作完整指南

《Python自动化处理PDF文档的操作完整指南》在办公自动化中,PDF文档处理是一项常见需求,本文将介绍如何使用Python实现PDF文档的自动化处理,感兴趣的小伙伴可以跟随小编一起学习一下... 目录使用pymupdf读写PDF文件基本概念安装pymupdf提取文本内容提取图像添加水印使用pdfplum

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说