Storage Driver Architecture(存储驱动体系结构)
来自APP或者内核组件的I/O请求经过I/O系统服务以及像文件系统驱动这样的上层驱动到达Storage class driver,Storage class driver将其翻译为系统定义的SCSI请求块(SRBs),其中SRB包含SCSI命令描述符块(CDBs),然后再将IRP发送到下层驱动(storage port driver或者intervening filter driver),好像设备就是一个SCSI设备一样(实质可能不是SCSI设备)。Storage port driver将来自Storage class driver的SRBs翻译为总线指定的命令,然后将所得命令发送到storage HBA,这期间需经过I/O总线驱动(可能)以及一个或多个过滤驱动。
Storage port driver为Windows NT的所有storage class drivers提供了一个接口。这些存储类驱动包括disk、tape、CDROM、DVD和changer类驱动。存储端口驱动将存储类驱动与各自所连接的HBA的适配器指定的请求进行了隔离。操作系统为SCSI、IDE、USB和IEEE 1394适配器都提供了存储端口驱动。
为SCSI总线服务的storage port driver将带有CDBs的SRBs传递到HBA指定的独立于操作系统的SCSI miniport driver。SCSI miniport driver是动态连接到SCSI port driver上的,以为SCSI HBA提供硬件特定的一些支持。
为IDE/ATAPI 或者IEEE 1394总线服务的storage port driver将接收到的来自storage class driver的SRBs翻译成下层适配器所要求的格式,比如,根据这些总线特定的传输协议重新打包CDBs,或者将它们翻译成不同的格式,以便将上层驱动从下层总线的特性中隔离开来。
上层或下层storage filter driver支持系统提供的storage class driver所不提供的设备特定的功能。下层过滤存储驱动监控SRBs和/或storage class driver发送的IRPs,并根据需要做相应的修改,然后才发送到下层驱动(storage port driver或者其它storage filter driver)。
Storage class driver利用SCSI port/class接口去控制存储类设备,系统为这些设备所连接的总线提供了storage port driver。
设备所连接的总线的类型以及该总线的storage port driver的实现对上层驱动是透明的。Storage port driver需要根据port/miniport driver体系结构,比如SCSI port driver;或者根据控制一个单一的、标准的硬件片,比如IDE/ATAPI port driver的一个庞大的驱动;或者根据某个过滤驱动,将接收到的SRBs翻译成不同的驱动栈所要求的格式,比如IEEE 1394 port driver。
Storage Drivers and Device Objects(存储驱动和设备对象)
存储设备堆栈由一棵设备对象树组成。这棵设备对象树是由处理发送给存储设备的I/O的驱动创建的。该设备对象树的根是一个FDO,该FDO是为存储适配器或者其它集成到该存储设备堆栈的驱动堆栈而创建的。该设备对象树上的设备对象都是供文件系统和APP使用的。
和其它所有的PnP driver一样,storage class driver或者storage filter driver将其自身添加到该设备对象树中。这个过程是在AddDevice例程中实现的:先调用IoCreateDevice创建设备,再调用IoAttachDeviceToDeviceStack将所创建的设备添加到设备堆栈的顶层上。
Tape miniclass、Medium Changer miniclass以及SCSI miniport driver不需要将创建的设备对象挂到设备堆栈上,而是由系统提供的tape class、changer class或SCSI port driver来处理这些任务。
Storage port drivers创建的PDOs类型是FILE_DEVICE_MASS_STORAGE。Disk class、CD-ROM class、Tape Class和Changer class drivers创建的FDOs的类型分别是:FILE_DEVICE_DISK、FILE_DEVICE_CD_ROM、 FILE_DEVICE_TAPE和 FILE_DEVICE_CHANGER。
SCSI HBA设备对象实例
(1)Storage bus driver为storage bus创建FDO(PCI bus FDO),并挂到由PnP管理器创建的storage bus PDO上。在storage bus FDO以下的设备对象树的结构取决于storage bus以及其如何集成到系统中的。在端口驱动层之上的Storage drivers不能与storage bus driver下层的对象进行交互。
(2)PCI bus driver枚举连接到该总线上的所有storage adapter,并为它们创建PDO。与各自adapter相对应的storage port driver创建一个FDO并挂到相应的PDO上。
上图中介绍了2个连接到PCI总线上的适配器的PDOs:一个代表IEEE 1394 Controller(请参考IEEE 1394 Controller设备对象实例);另一个代表SCSI HBA(Host Bus Adapter)。SCSI port driver和相关的miniport driver就会创建一个FDO并挂到SCSI HBA的PDO上。
(3)Storage port driver为挂到起适配器上的目标设备创建一个虚拟的PDO,即虚拟化目标设备(比如SCSI Adapter FDO)。上图中,介绍了SCSI port/miniport drivers创建的2个PDOs:一个代表HDD,另一个代表CD-ROM。
(4)一个或多个过滤驱动可以将一个过滤设备对象(filter DO)挂到storage port driver导出的目标设备PDO上。这样的filter DO可以截取并修改class driver发送到目标设备的请求。上图中,介绍了CD audio filter driver将一个filter DO挂到CD-ROM的PDO上。
(5)Storage class driver创建一个FDO,并将其挂到下层设备对象上。这里的下层设备对象可能是storage port driver导出的目标设备PDO,也可能是一个中间层过滤驱动挂到该设备堆栈上的一个filter DO。上图介绍了2个这样的FDOs:一个代表CD-ROM设备;另一个代表HDD的Partition 0。Partition 0代表整个原始磁盘,且不管磁盘是否分区,其都一直存在。
(6)Class driver也可以像总线驱动那样工作,当PnP管理器查询其子设备(IRP_MN_QUERY_DEVICE_RELATIONS with BusRelations)时,该类驱动返回一个PDOs的列表。例如,像可移动硬盘这样的已被分区的媒体设备驱动就可能返回代表其分区的PDOs列表。高层驱动则可以将其FDOs挂到这些PDOs上。上图中介绍了3个这样的PDOs,每一个都代表一个磁盘分区,该磁盘分区可以被当做一个目标设备。在固定的硬盘中,分区管理器挂到代表Partition 0的FDO上,并处理所有分区上的PnP操作。分区管理器的活动对磁盘class driver和所有上层过滤驱动来讲是透明的。
(7)在Class driver之上可以有一个或多个过滤驱动。与下层过滤驱动不同的是,上层过滤驱动截取发送到class driver的IRPs,并可修改它们;它们还可以截取所有的read-write请求并根据需要决定是否传输数据,并定义额外的I/O control codes(IOCTLs),例如,要求APP提供密码或其它相关信息。上图中介绍了一个磁盘加密过滤驱动创建的filter DO,该filter DO被挂到代表磁盘Partition 1的PDO上。
IEEE 1394 Controller设备对象实例
(1)SCSI Adapter PDO以上的storage bus FDO的设备树,请参考SCSI HBA设备对象实例。
(2)IEEE 1394驱动堆栈中最顶层的驱动创建了一个SBP2磁盘设备PDO。IEEE 1394驱动堆栈最终发送SBP2命令到IEEE 1394总线上的目标CD-ROM设备。
(3)系统提供的IEEE 1394 storage port driver被当成一个过滤驱动,其创建一个filter DO并挂到SBP2磁盘设备PDO上。IEEE 1394 storage port driver将来自CD-ROM class driver的SRBs翻译成SBP2命令,这些命令将被发送到下层的IEEE 1394驱动堆栈中。该驱动提供给下层storage drivers的接口与SCSI HBA设备对象实例中介绍的SCSI port/miniport driver提供的接口一样。
(4)CD –ROM class driver创建一个FDO并将其挂到下层设备对象上。这里的下层设备对象可能是一个SBP2 port filter DO,也可能是其它过滤驱动挂到该设备堆栈上的filter DO。
(1)PCI bus driver枚举USB host controller。系统加载USB port driver(usbport.sys)和配套到miniports(上图为提示)。之后,usbport.sys为该USB host controller创建一个FDO。
(2)USB port driver从根hub开始枚举系统中的USB hubs。Usbhub.sys驱动管理所有的USB hubs。上图仅展示了一层hub设备对象,但USB是允许hub设备级联的,所以在该设备树上可能潜在地存在很多hub设备对象。Hub driver检测并枚举USB mass storage device并为它们各自创建一个PDO。
(3)Windows提供了一个USB storage port driver (usbstor.sys),该驱动在USB堆栈和原始的Windows storage class drivers之间提供一个接口服务。Usbstor.sys创建其自己的FDO。Usbstor.sys可以将物理存储设备分割成多达16个逻辑单元。以上图所描述的为例,USB存储设备为Compact Flash device和Smart Media device提供了相互独立的Slots。所以,在这个例子中,usbstor.sys创建了2个独立的PDOs:一个代表Compact Flash device;另一个代表Smart Media device。
(4)usbstor.sys之上的堆栈由原始的disk class driver按普通方式管理。Disk class driver为Partition 0(代表整个磁盘) 创建一个PDO和一个FDO,并为每个分区创建一个PDO。
(5)分区管理器为每个磁盘分区创建一个FDO。
存储类驱动介绍
无论mass storage device挂在什么类型的总线上,storage class driver都会利用已经建立好的SCSI class/port接口来控制它们。当然,系统会为挂载了mass storage device的总线提供storage port driver(目前有:SCSI、IDE、USB和IEEE 1394)。Mass storage device所挂载的总线到底是什么类型,对storage class driver来将是透明的。
所有storage class driver都需要处理来自APP或上层驱动的I/O请求,然后穿过下层过滤驱动,最后到达storage port driver。Storage class driver的上层驱动主要是创建包含CDBs的SRBs,然后作为IRP的一个参数,并将该IRP发送给storage class driver。
Storage class driver在SRB中不提供寻址信息,而port driver(或一个still-lower driver)负责处理所有的寻址请求。Storage port driver将SRBs翻译成下面的HBA所要求的格式的命令并发送到设备。这里下面的HBA可能是SCSI HBA、1394 HBA、IDE Controller或其他类似的硬件。在WDK中,“HBA”代表下层类似的适配器或控制器。
Storage class driver必须实现DispatchSystemControl例程,以处理system-control IRPs。
(一般功能) Storage Class Driver's General Functionality
相对于storage port driver来讲,storage class driver是一个高层驱动,其实现了具体设备类型的功能。一般情况下,所有的storage class driver都需完成一下功能:
声称 PnP管理器传递到其AddDevice例程中的所有PDO(由PnP管理器创建)所代表的设备。
为每一个PDO创建一个FDO,并挂到其设备堆栈上。
如果该storage class driver控制的是一个可分区的设备,则其还需为每个分区创建一个PDO,并相应枚举请求。
解析系统I/O请求(IRPs)。
将IRPs映射为SCSI class/port接口请求(带有SCSI CDBs的SRBs)。
为请求建立超时值(不同的设备类型,超时值可能不同)。
将数据传输大小限制到适合下层HBA的值。(将一个IRP分成多个IRP)
处理storage port driver没有处理的错误,比如check-condition状态或者总线重置。