典型IO处理
=========
多数的IO操作并不涉及到IO系统的所有组件. 一个典型的IO请求起始于一个应用程序执行一个IO相关的函数(比如说, 从一个设备中读取数据), 这个函数由IO管理器, 加上一个或多个设备驱动程序, 还有HAL来处理.
正如刚才所说, 在Windows中, 线程在虚拟文件上执行IO操作. 操作系统将所有的IO请求抽象为在一个虚拟文件上的操作, 隐藏了IO操作可能不是针对一个文件结构的设备的事实. 这些抽象合成了一个应用程序对设备的接口. 一个虚拟文件会与任何的IO源设备或IO目的设备向关联, 这些设备被当做文件一样的对待(比如文件, 目录, 管道, 和邮件槽) 所有读取的字节或者写入的字节都被简单的认为是指向这些虚拟文件的字节流. 用户态应用程序(不关事Windows 或者POSIX)调用API来完成对操作系统内部的IO系统函数的调用, 完成从文件读取, 写入文件和其他的操作. IO管理器动态的将这些请求引导至合适的设备驱动程序. 下图说明了一个典型IO请求的过程.
设备驱动
为了与IO管理器和其他的IO系统组件整合, 设备驱动程序必须让自身的管理设备的角色与它针对某种设备管理的实现相一致.
设备驱动的类型
========
Windows支持一系列的驱动程序类型和编程环境. 甚至在一个设备驱动类型中, 编程环境都可能不一样, 这取决于驱动程序想要操纵的设备的类型. 范围最大的驱动类型分类就是看它是一个用户态的驱动程序呢, 还是一个内核态的驱动程序. Windows支持的用户态的驱动程序有:
这里, 我们的精力会集中在内核态的设备驱动上. 内核态的驱动程序有很多种, 大致可以分成以下几类:
WDM驱动
=========
WDM驱动是附着在Windows Driver Model(WDM)上的设备驱动. WDM包括对Windows的电源管理的支持, 对即插即用的支持, 对WMI的支持, 还支持大多数的附着在WDM上的驱动程序. WDM在Windows, Windows98还有Windows Me上实现的, 所以WDM驱动程序与这些版本的操作系统在原始程序上是兼容的, 并且在某些情况下, 在二进制上也是兼容的. 有以下三种类型的WDM驱动:
在WDM中, 没有一个驱动程序负责控制一个特定设备的方方面面. 总线驱动负责检测总线成员关系的变化(设备添加, 设备移除), 帮助PnP管理器来遍历所有的总线上的设备, 访问总线相关的注册表配置, 在某些情况下, 还控制总线供给设备的电环. 功能驱动基本上是唯一访问设备硬件的驱动程序.
注意: 在Windows2000, XP, 2003中, HAL拥有与在Windows NT中不同的角色. 在Windows2000之前, 希望添加本来不支持的硬件总线支持的第三方的硬件厂商不得不实现自己的HAL. Windows2k, windowsxp和Windows 2003允许第三方来实现总线驱动来为不支持的硬件总线提供支持.
分层的驱动
========
对一个个体硬件的支持可以通常拆分为几个驱动, 每个驱动提供让设备正常工作的功能支持的一部分. 出了WDM总线驱动, 功能驱动和过滤驱动, 赢家支持可以在以下的几个组件中拆分开来.
一个例子会帮助演示一下设备驱动如何工作的. 一个文件系统驱动程序接受了一个要向在某个文件中的某个特定地点写入数据的请求. 它将这个请求转化为一个向硬盘中某个特定的"逻辑上"的文件写入一组字节的请求. 然后, 它就传递(通过IO管理器)这个请求到一个简单的磁盘驱动程序. 这个磁盘驱动程序, 依次地, 将请求转换到一个磁盘的物理位置(cylinder/track/sector )(磁柱/磁道/扇区), 然后操控磁头来写入数据. 这个分层的过程见下图:
上图说明了在两层驱动程序之间的劳务分配. IO管理器收到了一个从某个文件的某个位置开始写入数据的请求. IO管理器传递请求给文件系统驱动程序, 文件系统驱动程序将从与文件相关的操作转换成为在磁盘的某个起始位置开始的写入, 还有送过来的一些字节. 文件系统调用IO管理器来传递这个请求给磁盘驱动程序, 磁盘驱动程序在讲请求转化为磁盘物理位置的写入操作, 将那些字节写入磁盘中.
因为所有的驱动程序, 文件系统驱动和设备驱动都一样, 都存在于相同的操作系统架构之中, 另一个驱动可以被很容易的插入到架构层次中来, 而不需要修改现有的IO系统的驱动. 比如说, 好几个磁盘可以被看作是一个很大的单个磁盘, 所需要做的就是添加一个新驱动而已. 这样的在windows中存在的驱动提供磁盘容错支持. (然而在所有版本的windows中, 是由服务器版本的包括fault-tlerant disk support). 这种逻辑上的, 体积管理器驱动存在于文件系统驱动和磁盘驱动之间, 下图可以详细说明.