目前大多数的外部存储设备(例如USB活动硬盘等)基本上都采用FAT文件系统,用户可以像
使用主机硬盘一样利用资源管理器对外部存储设备上的文件执行各种操作。在Windows环境
下,外部存储设备的驱动程序除要完成普通的I/O读写操作之外,还需要构造文件系统接口,
以实现Windows环境下磁盘的逻辑操作到物理操作的转换。下面以一个虚拟设备为例,介绍
在Windows环境下构造文件系统驱动程序的基本原理和方法。 
Windows的文件系统 
Windows系列操作系统采用IOS(Input/Output Supervisor,输入输出管理程序)技术。IOS
管理所有的存储设备,如IDE硬盘、可移动式软盘、CDROM等。IOS的接口以及其在操作系统
中的逻辑层次(暂不考虑SCSI结构)如下图所示。 
我们从图中可以看到Windows采用的是一种分层的、可安装的文件系统,每一层都完成一特定
的功能,层与层之间是相对独立的实体。我们要创建自己的文件系统驱动,一般不需要对每
一层都提供服务,比如我们采用硬盘上的FAT文件系统时,可以先利用VFAT.VXD作FSD(File
 System Driver,文件系统驱动器),再用DISKTSD.VXD模拟硬盘物理行为。而我们真正需要
做的只是编写自己的端口驱动程序,以响应基于物理或逻辑分区的读写操作。 
构造文件系统驱动程序 
在IOS初始化阶段,它将在SYSTEM\IOSUBSYS目录下搜索后缀为PDR(Port Driver)、MPD
(SCSI Miniport Driver)、VXD(FSD、TSD等)的设备驱动程序,并向它们发送
SYS_DYNAMIC_DEVICE_INIT消息。为了响应IOS,端口驱动程序在响应SYS_DYNAMIC_DEVICE_INIT
消息时填写DRP(Device Request Packet)结构并调用IOS_Register向IOS注册。DRP结构的
AEP域中包含的是回调地址,在端口驱动程序装载后,IOS就通过发送AEP对DRP结构进行初始
化。典型的AEP响应代码如下: 
VOID __cdecl SAMPLE_Aer(AEP* pAep) 

switch (pAep->AEP_func) 

//IOS最先发送此消息 
case AEP_INITIALIZE: 
……//创建并填写DDB(Device Driver Block) 
//返回AEP_SUCCESS表示创建成功 
pAep->AEP_result = AEP_SUCCESS; 
break; 
//DDB成功创建后,IOS发送此消息 
case AEP_DEVICE_INQUIRY: 
pDcb = ((AEP_inquiry_device*)pAep)->AEP_i_d_dcb; 
if (((DCB*)pDcb)->DCB_unit_on_ctl=0) 

……//第一次发送此消息时创建用于虚拟设备的DCB(Device Control Block),DCB将被
用于描述虚拟设备的存储容量、最大传输能力等参数 
pAep->AEP_result = AEP_SUCCESS; } 
else 
//由于只创建一个虚拟设备,所以返回AEP_NO_MORE_DEVICES终止发送此消息 
pAep->AEP_result = 
AEP_NO_MORE_DEVICES; 
break; 
case AEP_CONFIG_DCB: 
//IOS在终止AEP_DEVICE_INQUIRY消息发送后,发送此消息为我们创建的虚拟存储设备分配
驱动器号(C: D: E:等) 
//返回AEP_SUCCESS表示成功 
pAep->AEP_result = AEP_SUCCESS; 
break; 
//初始化结束时IOS 发送此消息 
case AEP_BOOT_COMPLETE: 
//返回AEP_SUCCESS,通知IOS将端口驱动程序驻留在内存中 
pAep->AEP_result = AEP_SUCCESS; 
break; 
default: 
break; 


在初始化结束后,IOS便通过端口驱动程序在AEP_CONFIG_DCB消息响应中登记的IO请求响应
函数,发送IOP(IO Request Packet)完成物理的读写。典型的IO请求响应函数代码如下: 
VOID __cdecl SAMPLE_RequestHandler(IOP* pIop) 

switch (pIop->IOP_ior.IOR_func) 

//检查驱动器介质是否存在 
case IOR_MEDIA_CHECK_RESET: 
//非移动式磁盘始终返回IORS_SUCCESS 
pIor->IOR_status = IORS_SUCCESS; 
break; 
//驱动器读操作 
case IOR_READ: 
……//读成功则返回IORS_SUCCESS 
break; 
//驱动器写操作 
case IOR_WRITE: 
……//写成功则返回IORS_SUCCESS 
break; 
default: 
//处理不支持的命令 
pIor->IOR_status = 
IORS_INVALID_COMMAND; 
break; 


-- pIop->IOP_callback_ptr; 
pIop->IOP_callback_ptr->IOP_CB_address(pIop); 

端口驱动程序的读写操作实际上是以扇区为单位进行的,并不涉及到单字节的读写。另外,
一个TSD(Type Specific Driver)可以对应多个端口驱动程序,一个端口驱动程序可以同时
支持多个物理设备,并且每一个物理设备拥有独立的DCB。实际上,目前流行的虚拟光驱软
件就是利用此原理,通过编写端口驱动程序实现在硬盘上虚拟光驱操作的。最后值得指出
的是:本文所涉及的文件系统技术还可以用来实现在FAT分区上扩展类似于NTFS中的磁盘
数据加密和磁盘容量分配控制等高级功能。