I/O管理器执行IO完成

简介:

IO管理器的任务就是管理IO,本质上windows的IO操作都是异步的,这是由IO流的分层下递和IRQL共同决定的,效果就是IO流被处 理的每一个步骤都可能在任意线程上下文中进行,那么如果最下面的驱动完成了一个irp,这个怎么让上面的驱动知道呢?当然方法很多,比如上层驱动等待在一 个event上,而microsoft的作法显然更好,就是为每一个irp流经的每一个设备提供了一个选择,该设备的驱动可以提供一个回调函数,以便下层 驱动完成请求的时候通知该层,这就是IO完成回调函数,按照常规理解,这个函数应该由下层的驱动调用,而实际上这样做的话,实现就不是那么“结构化”了, 驱动的开发者就必须负责去手工调用该函数,失去了回调本来的含义,增加了驱动开发者的负担,因此这个回调函数就由IO管理器来调用,这里的说法仅仅是按照 模块化思想来的,在整个windows内核中你实际上看不到一个叫做IO管理器的模块的,所谓的IO管理器就是一系列函数接口,对于IO完成回调函数的调 用,你只需要调用一个IofCompleteRequest就可以了,而这个接口的实现就是IO管理器的重要内容,那么它是怎么实现的呢?如果不看 ReactOS的代码,也不反汇编windows内核的话,还有一种情况能够得到它的实现,那就是自己想,我就是这么干的,没想到还真蒙对了。

在分层的驱动逐次往下层的设备递交irp的过程中,只要有一个分发函数调用了IofCompleteRequest,那么该irp就不会再往下走了,而是 顺着来的方向的反方向逐个的调用irp栈上的IO完成回调函数,因此IofCompleteRequest的实现首先就是遍历所有的irp栈帧,然后在每 一个上执行其IO完成回调函数即可,这只是最简单的方式,windows内核的逻辑也是这么来的,但是往往自己能想到的都是最简单的,扩展开来的话会有很 多自己想不到的,比如有一种情况就是irp栈某一层完成了io,IO管理器调用了上层的io完成回调,接下来该回调返回以后,IO管理器会接着调用上上层 的io完成回调,然而如果这个上层的io完成回调中如果一个数据没有准备好,而上上层io完成回调中又需要这个数据的话,这就会引起问题,IO管理器直接 调用了上上层的io完成回调,而实际上这个上层的io还没有完成呢(一个数据没有到位)。以上这种情况是很常见的,毕竟windows内核是一个本质上异 步的操作系统内核,一个irp到达某个层次后可能为了实现某项功能会进行一些别的操作,比如查询一些信息,比如和别的内核模块进行交互,这都会产生另外的 irp,而这些irp是和上层没有关系的,是在本层产生并下发的,因此如果这些irp不完成,那个本来的irp也就算没有完成,因此虽然下层完成了这个本 来的irp,只因为这些额外的我们自己在本层生成的irp还没有完成,这就意味着IO完成不能这么简单的逆流而上,实际上最简单的方式就是告诉IO管理 器,也就是告诉IofCompleteRequest不要继续逆流而上了,等到时机成熟的时候,我自己逆流而上,这就是IO完成回调函数 STATUS_MORE_PROCESSING_REQUIRED返回值的含义,IofCompleteRequest一旦接收到某个回调函数的返回值是 这个,那么就终止循环,然后退出IO管理器,等到这个层次的所有数据都准备好之后,该驱动自行调用IofCompleteRequest,这将重复同样的 过程,只是起点变化了,不是最底层的驱动了,而是该层驱动,也就是因为数据而等待的驱动,数据可以在io完成中被准备好,也可以是别的,这就是另外的话题 了。

最终irp会回到它生成的地方,到这里之后,大多数情况下仍然是任意线程上下文,因为最底层驱动的完成是靠中断触发,所以一系列的逆流而上就是在DPC中 执行的(DPC在cpu的队列中排队,为了延迟执行硬中断任务,而APC在线程队列中排队,执行线程上下文中执行的任务),因此为了将完成消息通知到发出 请求的线程,就需要将最后的irp层次的io完成回调函数排入到该线程的apc队列中,然后最终在该线程的上下文中被执行,实际上排入apc队列的是 IopCompleteRequest函数。底层驱动不能立马完成的irp,返回时一定要设置pending状态,这样上层才可以正确处理完成回调函数, 注意,这个pending和STATUS_MORE_PROCESSING_REQUIRED的含义是不同 的,STATUS_MORE_PROCESSING_REQUIRED是自己来处理接下来的完成回调,而pending则是指示io还没有完成,可是完成 回调却要调用,为了防止阻塞,真正的完成操作将在dpc/apc中进行。


 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1273452


相关文章
|
4月前
|
IDE 开发工具
virsh io_cache_mode 虚拟机io种类
virsh io_cache_mode 虚拟机io种类
47 0
|
3月前
|
Java 数据处理
fastdfs源码阅读:文件传输原理与网络IO模型(accept线程、work线程(网络io处理)、dio线程(文件io处理))
fastdfs源码阅读:文件传输原理与网络IO模型(accept线程、work线程(网络io处理)、dio线程(文件io处理))
44 0
|
3月前
|
缓存 Java 程序员
网络IO管理-简单一问一答、多线程方式
网络IO管理-简单一问一答、多线程方式
|
9月前
|
缓存 Linux C语言
基础IO+文件(一)
基础IO+文件
50 0
|
9月前
|
编译器 Linux vr&ar
基础IO+文件(三)
基础IO+文件
46 0
|
9月前
|
存储 Linux 块存储
基础IO+文件(二)
基础IO+文件
42 0
|
10月前
|
Linux
day26-系统IO(2022.2.23)
day26-系统IO(2022.2.23)
100 1
|
Java API
Java IO基础(同步阻塞IO)
Java IO是一套Java 用来读写数据(输入和输出)的API,大部分程序都需要处理一些输入,并由输入产生一些输出(PS: 输入和输出是相对CPU而言的,input 就是从外面到CPU,output就是从CPU到外面,CPU是主人公)。java.io 包下有大约80多个类,大概可以分成四组:
128 0
Java IO基础(同步阻塞IO)
|
数据库
操作系统第五章_01 IO设备的基本概念和分类 IO控制器 IO控制方式
操作系统第五章_01 IO设备的基本概念和分类 IO控制器 IO控制方式
361 0
操作系统第五章_01 IO设备的基本概念和分类 IO控制器 IO控制方式
|
XML JSON 移动开发
Qt-QML-C++交互实现文件IO系统-后继-具体文件IO的实现
在上一篇文章中,我大致将这个QML中的文件IO类搭出了大致的框架,那么,今天抽时间写了一点文件的读写,这里我使用的文件流来读写文件。
109 0
Qt-QML-C++交互实现文件IO系统-后继-具体文件IO的实现

热门文章

最新文章