WinCE的存储管理.doc_第1页
WinCE的存储管理.doc_第2页
WinCE的存储管理.doc_第3页
WinCE的存储管理.doc_第4页
WinCE的存储管理.doc_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第五章 Windows CE的储存管理本章将介绍Windows CE 的储存管理。我们将本章内容分为两大部分,前半部会依序介绍 Windows CE的档案系统类型、 Windows CE储存管理结构和每一个层次、以及如何自行开发档案系统并加载之,后半部则以Ramdisk上的档案系统为例,实际分析储存管理相关的原始程序代码与数据型态。5.1 Windows CE的储存管理架构5.1.1 概述 Windows CE提供了三种类型的档案系统:RAM-based 档案系统、ROM-based 档案系统、以及用于支持ATA (Advanced Technology Attachment) 装置和SRAM卡等外围储存装置的FAT档案系统。其中,前两种档案系统属于 Windows CE的内建档案系统,后者属于可安装性档案系统。另外,嵌入式系统的开发人员也可以编写自己的档案系统,并在系统中注册使用。Windows CE提供了platform-independent API,不论是何种储存装置,所有对档案系统的存取都是透过Win32 API完成。Windows CE预设的储存装置为最大可达256MB的RAM内存。RAM被分割为程序空间 (program memory) 和对象空间 (object store) 。程序空间和一般计算机系统中RAM的使用类似,用来储存执行程序及所需数据。对象空间则类似一般计算机系统中的硬盘,用来储存应用程序及档案。对象空间中存放的数据可分为三大类: (1) 档案系统 (file system) , (2) 注册信息 (registry) , (3) Windows CE数据库 (Windows CE database) 。Windows CE系统的电源管理机制,即使在关机状态时,仍旧有少量的电力从电池供应RAM,以保留储存在其中的数据。只有在电池电力完全耗尽时,RAM中储存的数据才会消失。与对象空间相关的RAM-based档案系统和ROM-based档案系统,是 Windows CE预设支持的内建档案系统。除此之外,使用者还可以安装用于支持外围储存装置的档案系统,比如FAT、UDFS等等。对外围储存装置的存取,都是透过这种可安装性档案系统来完成的。另外,我们还可以将一个外围储存装置,分为多个volume(卷)并分别加载,其中每个volume可以使用不同的档案系统。Windows CE没有像Windows XP或Windows ME使用磁盘驱动器代号来表示volume,加载后的volume在Windows CE内以目录的形式呈现。5.1.2 对象空间如前所述,对象空间的数据分为三部分档案系统、系统注册信息及数据库。然而,档案系统、数据库以及注册信息都不一定要储存在对象空间中,它们也可以被存放ROM或是外围储存装置中。数据的建立和使用,与实际的储存装置无关,只是依赖于储存的类型。操作系统负责管理内存堆,在必要的时候会对档案进行压缩和解压缩。对象空间使用基于事务的数据管理机制。如果当数据写入对象空间时,发生了电源中断的情况,Windows CE会透过各种手段保证对象空间不被破坏,例如在系统重启后继续完成该写操作,或是恢复到电源中断前的状态。在早期的Windows CE版本中,RAM档案系统和档案大小最大皆只能达16MB。到了Windows CE 3.0这个版本,RAM档案系统最大可达256MB,而档案大小最大也能达32MB。另外,对象空间中的对象数目也由原本的65,536增加到4,000,000左右。最新的Windows CE .NET允许档案最大可达4GB。Windows CE为对象空间中的每个对象,都分配了一个唯一的对象识别码 (Windows CE object identifier, 简称CEOID) 。对象识别码的作用就是用于存取对象空间中的对象。在对象空间中,以下列出的各项都可以被定义为一个对象: 注册信息中的一个键 注册信息中的一个值 一个档案 档案数据中大小为4KB的一部分 (意即一个12KB的档案本身会对应一个档案对象,另外其所含的三个4KB的数据块也分别对应着一个对象) 数据库中的一项记录 (最多可达4KB数据) 数据库中一项记录的扩展信息 (也可达4KB数据) 一个数据库 数据库的一个volume (a database volume)需要说明的一点是,Windows CE仅仅保证对象识别码在同一个volume中是唯一的,当有多个volume,可能在不同volume中发现相同对象识别码的对象。因此,Windows CE为每个数据库volume (database volume) 都分配了一个唯一的数据库识别码 (CEGUID)。数据库识别码和对象识别码的结合,就可以表示数据库volume中的某个对象了。要对对象空间中的对象进行存取,第一步就是获得该对象的对象识别码。根据不同的对象类型,Windows CE提供了相对应的函式以获得该对象的对象识别码,参考表5.1。表5.1 获得对象识别码函式对象类型获得对象识别码的方法目录或档案FindFirstFile和FindNextFile函式回传的WIN32_FIND_DATA结构的dwOID字段。GetFileInformationByHandle函式回传的BY_HANDLE_FILE_INFORMATION结构的dwOID字段。数据库CeCreateDatabaseEx2或CeFindNextDatabaseEx函式的回传值数据库记录CeSeekDatabaseEx、CeReadRecordPropsEx以及 CeWriteRecordProps函式的回传值。已加载的数据库volumeCeMountDBVol和CeEnumDBVolumes函式可以回传已挂载数据库volume中的数据库识别码。有了对象识别码,就可以使用CeOidGetInfoEx函式得到该对象内的数据。CeOidGetInfoEx函式会回传一个CEOIDINFO结构 (结构原型列于程序代码5.1)。CEOIDINFO结构有一个wObjType字段说明了对象的类型。假如该字段的值为OBJTYPE_DATABASE,就指这是一个数据库对象。由wObjType可得知该对象是档案、目录、数据库还是数据库记录,同时也得知该对象的数据地址。例如,如果对一个数据库对象使用CeOidGetInfoEx的话,那么回传的类型值为OBJTYPE_DATABASE,而与之相关的数据库名称、类型识别码、记录的数目、数据库的大小以及排序方式等信息,都将保存在一个CEDBASEINFO结构中。程序代码5.1 CEOIDINFO数据结构typedef struct _CEOIDINFO WORD wObjType; /Type of object/ OBJTYPE_INVALID| There was no valid object/with this CEOID/ OBJTYPE_FILE| The object is a file/ OBJTYPE_DIRECTORY| The object is a directory/ OBJTYPE_DATABASE | The object is a database/ OBJTYPE_RECORD| The object is a record inside/a databaseWORD wPad;/ dword alignmentunion /This is a unionCEFILEINFO infFile;/Valid for file objectsCEDIRINFO infDirectory;/Valid for directory objects/ CESYSGEN IF FILESYS_FSDBASECEDBASEINFO infDatabase;/Valid for database objectsCERECORDINFO infRecord;/Valid for record objects/ CESYSGEN ENDIF; CEOIDINFO, PCEOIDINFO;5.1.3 储存管理程序储存管理程序 (Storage Manager) 负责管理外围储存装置所使用的档案系统和区块装置驱动程序 (Block Device Driver) 。储存管理程序的功能实作位在fsdmgr.dll模块,它由三部分组成,包括区块装置管理程序 (Block Driver Manager) 、分割区管理程序 (Partition Manager) 以及档案系统管理程序 (File System Driver Manager,或简称FSD Manager) 。所有对档案和volume的处理,都是经由储存管理程序完成的,储存管理程序在永久性储存介质的存取过程中,扮演了很重要的角色。图5.1 储存管理程序结构图Windows CE的储存管理程序是一个分层结构 ,其结构如图5.1所示,因此做Disk I/O必需经过储存管理程序的各个阶层。首先是过滤器层 (File System Filter) ,在将I/O请求交由档案系统驱动程序处理之前,在过滤器这一层可以完成一些加密、压缩和病毒扫描等性质的额外工作。接下来是档案系统驱动程序 (File System Driver) ,在这里对参数进行格式化,将文件名称转换为区块装置驱动程序可以识别的物理地址。在这之后,就可以经分割区管理程序,或直接交由区块装置驱动程序,完成实体的I/O操作了。在储存管理程序的启动过程中,有很多信息是从系统的注册信息中得到的。例如,下面的注册信息会告知系统加载储存管理程序模块:HKEY_LOCAL_MACHINESystemStorageManager Dll=fsdmgr.dll另外,每当系统检测到新的外围储存装置时,装置管理程序会自动加载支持该装置的区块装置驱动程序,之后向储存管理程序报告,该装置的配置信息在注册信息中的位置。储存管理程序就是根据这些信息,决定如何加载适当的分割区驱动程序 (partition driver) 和档案系统驱动程序。下面是所有装置都可使用的预设配置信息:HKEY_LOCAL_MACHINESystemStorageManagerProfilesAutoMount=dword:1AutoPart=dword:0AutoFormat=dword:0MountFlags=dword:0DefaultFileSystem=FATFSPartitionDriver=mspart.dllFolder=Mounted Volume其中AutoFormat表明是否对该装置进行自动格式化,AutoPart表明是否用该装置上的最大可用空间自动建立分割区,AutoMount表明是否自动挂载每个检测到的分割区,而MountFlags则指出了应如何对分割区进行挂载。如果装置管理程序向储存管理程序,指定新装置的配置信息所在的位置,那么储存管理程序会使用该装置的指定配置信息。例如,硬盘的配置信息可能如下:HKEY_LOCAL_MACHINESystemStorageManagerProfilesHDProfile Name=IDE Hard Disk Drive Folder=Hard Disk对于未提供一些配置信息,比如AutoFormat、AutoPart和AutoMount,则要使用系统提供的默认值。当系统发现新的外围储存装置时,储存管理程序为其加载分割区驱动程序和档案系统驱动程序的程序如下:1 装置管理程序负责加载区块装置的驱动程序,2 由该装置发出一个通知,告知储存管理程序该装置的装置名称及其GUID,3 储存管理程序根据注册信息中的配置信息,为该装置加载分割区驱动程序,4 储存管理程序行举该装置上的所有分割区,5 储存管理程序为每个分割区,加载档案系统驱动程序。 档案系统过滤器档案系统过滤器和档案系统驱动程序类似,它们都有一组输出函式被CreateFile和 CreateDirectory这类的标准档案系统API映像到。二者不同之处在于,档案系统过滤器要提供HookVolume和UnhookVolume这两个函式,而档案系统驱动程序必须提供的是MountDisk和UnmountDisk这两个函式。档案系统驱动程序和档案系统过滤器的加载,都是透过档案系统管理程序完成的。有关档案系统过滤器的信息,也是保存在注册信息中。档案系统管理程序需要到以下各处搜寻应加载的档案系统过滤器:HKEY_LOCAL_MACHINESystemStorageManagerAutoLoadFileSystemFiltersHKEY_LOCAL_MACHINESystemStorageManagerProfilesProfileNameFileSystemFilters HKEY_LOCAL_MACHINESystemStorageManagerFileSystemFilters HKEY_LOCAL_MACHINESystemStorageManagerFilters 此处,FileSystem代表档案系统在注册信息中所使用的名称,例如FATFS、UDFS等等。如果在HKEY_LOCAL_MACHINESystemStorageManagerAutoLoadFileSystemFiltersHKEY_LOCAL_MACHINESystemStorageManagerProfilesProfileNameFileSystemFilters 中出现了一个过滤器的话,那么所有使用该配置信息的档案系统,都将使用该过滤器。如果在HKEY_LOCAL_MACHINESystemStorageManagerFileSystemFilters中出现了一个过滤器的话,那么名为FileSystem的档案系统将使用该过滤器。如果一个过滤器出现在HKEY_LOCAL_MACHINESystemStorageManagerFilters中,那么所有的档案系统都将使用该过滤器。下面是一个注册信息中有关过滤器信息的例子:HKEY_LOCAL_MACHINESystemStorageManager.FiltersFilterNamedll=filter.dllOrder=dword:x其中dll的值,是该过滤器所对应的动态链接库,Order的值,则是建造过滤器堆栈时各过滤器之间的顺序。 档案系统管理程序与档案系统驱动程序首先来看一下档案系统驱动程序 (File System DriverFSD) 。档案系统驱动程序只适用于区块装置。我们知道,任何装置加载系统后,都需要对应的装置驱动程序的配合才能得以工作,对于区块装置而言,自然也少不了区块装置驱动程序。但是与其它装置不同的是,区块装置除了需要直接和硬件沟通的区块装置驱动程序之外,还需要一个档案系统驱动程序,这是因为,虽然区块装置驱动程序已经向上层提供了各种函式接口,透过这些接口就可以对区块装置进行初始化、读写数据区块等等各种操作了,但是这种接口的操作对象却是数据区块,如果直接将这种接口提供给使用者使用的话,使用者所见到的区块装置就是一个杂乱无章、毫无规律的数据区块集合,这对使用者而言非常地不方便。因此必需将这些散乱的数据区块,组织成档案的形式,并向使用者提供一个按名存取的档案系统接口,这就是档案系统驱动程序的主要功能。意即档案系统驱动程序建立在区块装置驱动程序模块之上,负责对区块装置的进一步抽象,把毫无规律的数据区块,组织成对使用者来说,更为方便易用的档案,并向上提供了档案操作的函式接口。档案系统程序与区块装置驱动程序间的关系如图5.2所示。File 1File 2File k档案系统驱动程序区块装置驱动程序B 1B 2B n图5.2 档案系统驱动程序和区块装置驱动程序关系图Windows CE支持大多数Windows XP或Windows ME使用的档案I/O函式,例如CreateFile、ReadFile、WriteFile和CloseHandle等Win32 API呼叫。同时,Windows CE仍然遵循使用句柄对档案进行存取的传统方法。由CreateFile函式回传,新建立或打开的档案句柄,之后的读写操作,都使用该句柄来决定档案操作的对象。当然,对读写操作来说,还需要一个指标,来指出在档案中进行读写的位置。系统中所有的可安装档案系统,都是由档案系统管理程序负责管理的。每个可安装档案系统,都对应着一个档案系统驱动程序,并且以动态链接库 (Dynamic Link Library) 的形式提供,它有一组输出函式被映像到标准的档案系统Win32 API上。像CreateFile、ReadFile、WriteFile和CloseHandle这些档案系统API的功能,最后都是呼叫某个档案系统驱动程序的函式MyFSD_CreateFileW、MyFSD_ReadFile、MyFSD_WriteFile和MyFSD_CloseFile完成的。另外值得注意的一点是,档案系统驱动程序的动态链接库的名字,与该档案系统驱动程序的输出函式的前缀 (prefix) 是相同的。例如,如果档案系统名为MyFSD,那么对应的动态链接库就是MyFSD.dll,其输出函式的前缀为MyFSD_*。在应用程序中存取可安装档案系统,使用的是标准的档案系统Win32 API。例如,当应用程序想要在某个储存装置上建立一个目录时,可以呼叫CreateDirectory。之后由档案系统管理程序对CreateDirectory中指明的路径加以识别,如果发现该路径指向一个使用可安装档案系统的装置,便会呼叫相对应的档案系统驱动程序MyFSD.dll内的建立目录函式MyFSD_CreateDirectoryW。也就是说,应用程序呼叫CreateDirectory的结果,是导致档案系统管理程序,呼叫相对应档案系统驱动程序的函式MyFSD_CreateDirectoryW。在Windows CE中,负责管理档案系统驱动程序的模块,称为档案系统管理程序 (File System Driver Manager) 。由于现代操作系统一般都支持多个档案系统并存,因此需要对系统中用到的各个档案系统加以管理,这就是档案系统管理程序的作用。从功能上讲,Windows CE中的档案系统管理程序与Linux中的虚拟档案系统VFS类似,如图5.3所示。首先,作为不同的档案系统,它们向上层提供的函式接口必然也是不同的。但是,如果为了使用系统中不同的档案系统,就必须记忆多套不同的函式接口,这对使用者来说是难以接受的。我们所希望的是向使用者提供一套CreateFile、ReadFile、WriteFile和CloseHandle这样的标准接口,为使用者隐藏掉不同的档案系统间的差异。这个任务就是由档案系统管理程序来完成的。在Windows CE中,使用者见到的并不是档案系统驱动程序所提供的接口,而是经过档案系统管理程序统一包装过的Win32 API函式接口。这种统一接口的作法虽方便了使用者,但另一方面却又不可避免的带来了系统复杂性。对使用者而言,使用者根本不用关心,他所使用的档案所在的volume到底使用何种档案系统,因为档案系统管理程序已经为使用者隐藏了其中的细节,但是在进行的实际的档案操作时,我们又必须要能够找出对应的档案系统,这也是由档案系统管理程序来完成的。在Windows CE中没有目前目录 (current directory) 的概念,所有对档案的存取都必需提供完整路径名称。在为外围储存装置安装档案系统驱动程序的同时,档案系统管理程序会为其注册一个标识性的目录名称。如此一来,当使用者对外围储存装置上的档案进行存取时,档案系统管理程序就可以根据使用者提供的完整目录名称,分析出该档案所在的volume、使用的档案系统等。.Standard file system Win32 API档案系统管理程序FSD 1FSD 2FSD n图5.3 档案系统管理程序与档案系统驱动程序关系图 分割区管理程序与分割区驱动程序一个储存装置是由多个扇区 (sector) 组成的,每个扇区包含了一组连续的字节,所有扇区的大小都是相同的。储存装置可能被划分为多个逻辑分割区,每个分割区由一组连续的扇区组成。分割区之间不能相互重迭,否则操作系统将停止响应。没有被划分到任何分割区中的储存空间属于未分割区空间。分割区管理程序是储存管理程序的一部分,它透过呼叫分割区驱动程序来完成对这些分割区的管理、挂载 (mount) 与卸载 (unmount)。同一储存装置上的不同分割区可以使用不同的档案系统,每个分割区所使用的档案系统类型是在建立或格式化时就确定了。在对该分割区进行挂载时,分割区管理程序会通知储存管理程序启动对应的档案系统。Windows CE可以同时支持多个分割区驱动程序,但是对于一个指定的储存装置来讲只能使用一个分割区驱动程序,由它为分割区管理程序解释该装置上的所有分割区。如前所述,分割区是对储存装置进行逻辑划分的结果。在Windows CE中,多个分割区既可以使用相同的档案系统,也可以使用不同的档案系统。分割区管理程序透过呼叫分割区驱动程序完成对分割区的操作。分割区驱动程序也是以动态链接库的形式提供的,在Windows CE中预设的分割区驱动程序是MSPart.dll,它输出了一组API。使用者也可以编写自己的分割区驱动程序,只要该分割区驱动程序支持与MSPart.dll相同的API即可。为了使自己编写的分割区驱动程序MyPart.dll生效,还需要在注册信息的配置信息中填写PartitionDriver=MyPart.dll,这样就可以使用自己的分割区驱动程序了。表5.2说明了一个分割区驱动程序应该提供的所有函式。表5.2 分割区驱动程序提供的函式函式名功能PD_ClosePartition结束I/O操作,关闭分割区PD_CloseStore关闭储存装置上的volumePD_CreatePartition在储存装置的volume上建立分割区PD_DeletePartition从储存装置的volume上删除分割区PD_DeviceIoControl向指定的装置驱动程序直接发送句柄,完成相对应的操作PD_FindPartitionClose关闭列举分割区时使用的搜寻句柄PD_FindPartitionNext在列举分割区时得到下一个分割区的信息。PD_FindPartitionStart开始列举分割区。PD_FormatPartition在储存装置的volume上格式化一个分割区PD_FormatStore对储存装置进行格式化操作PD_GetPartitionInfo得到指定分割区的属性信息PD_GetStoreInfo得到储存装置的信息PD_IsStoreFormatted查询储存装置是否已被格式化PD_OpenPartition打开分割区以进行I/O操作PD_OpenStore打开储存装置上的volumePD_RenamePartition重新命名储存装置上的一个分割区PD_SetPartitionAttrs设定指定分割区的属性 区块装置管理程序区块装置的读写操作都是以区块 (block) 为单位,而不是以字节为单位进行的。区块的大小都是固定的,常用的有512 字节、1 KB、2 KB和4 KB。区块装置驱动程序通常都会向上层提供一个串流 (stream) 的接口,应用程序透过使用CreateFile和ReadFile这些标准的档案系统API对区块装置进行存取。当应用程序呼叫ReadFile对区块装置进行存取时,档案系统会先找到对应的逻辑区块,检查这些逻辑区块是否保存在缓存区 (buffer) 中。如果在的话,则可直接由缓存区中读取数据,否则就需要透过区块装置驱动程序对实际的区块装置进行读取操作了。当一个区块装置驱动程序加载系统中时,它会通知储存管理程序这一个加载事件,作为对此事件的响应。储存管理程序将负责查询与此区块装置驱动程序相关的注册信息,并通知分割区管理程序加载对应的装置。5.1.4 档案系统驱动程序的建立与加载Windows CE提供了一套模板式方法,使得开发人员可以轻松地开发一套新的档案系统。新开发的档案系统既可以充分利用储存装置的特性,也能够限制储存装置的档案操作。 档案系统驱动程序的建立档案系统驱动程序为一个有一组输出函式被映射到Win32 API上的动态链接库。当应用程序呼叫Win32 API来操作档案时,如果发现要操作的档案位于某一档案系统的volume上,那么档案系统管理程序会将该系统呼叫,映像到该档案系统相对应的输出函式,藉由该档案系统驱动程序的输出函式来操作档案。Windows CE还提供了一个档案系统驱动程序的开发模板,开发人员只要提供各种所需的输出函式就可以了。通常,一个档案系统驱动程序应该提供所有的输出函式,但这并不是必要的。例如,如果开发人员所开发的档案系统驱动程序不允许使用者建立或删除目录,只要在档案系统驱动程序中不提供CreateDirectory和RemoveDirectory这两个输出函式即可。档案系统驱动程序没有提供的输出函式,将由档案系统管理程序自动填入stub function代替,一般stub function只会回传ERROR_NOT_SUPPORTED。因此,在前面的例子中,当应用程序尝试建立或删除目录时就会失败。除了提供Win32 API需映像到的输出函式,档案系统驱动程序还要提供FSD_MountDisk和FSD_UnmountDisk这两个函式。当系统要安装或移除某个档案系统驱动程序时,装置管理程序会呼叫这两个函式。如果要开发一个名为MyFSD的档案系统驱动程序,那么该档案系统驱动程序的动态链接库必须命名为MyFSD.dll。该动态链接库中要包含了数据类型的定义、标头档案 (header file) 以及MyFSD所支持的输出函式。PVOLUME、PFILE和PSEARCH这三种数据预设都是DWORD类型的,分别用于储存已载入的volume、档案和搜寻句柄的信息。然而,我们也可以在MyFSD.dll中对这三种数据类型重新进行定义,使它们包含我们所需要的信息。例如,我们可以将它们定义为指向某种结构的指针。需要注意的一点是,这种重新定义必须在纳入标头档案Fsdmgr.h之前进行,否则将使用预设的定义。编译生成MyFSD.dll的程序代码中必须包含Fsdmgr.h,该档案中包含了所有的输出函式原型宣告。前面已经讲过,在纳入Fsdmgr.h之前可以对PVOLUME、PFILE和PSEARCH这三种数据类型重新定义。除此之外,我们还必须定义一个FSDAPI常数,此常数决定了档案系统名称、所有函式前缀以及最后生成的动态链接库名称。程序代码5.2说明了如何在MyFSD.dll中纳入Fsdmgr.h。程序代码5.2 在MyFSD.dll中纳入Fsdmgr.h/ This defines a type that is a pointer to a structure containing / two DWORDs.typedef struct DWORD first_field;DWORD second_field; TWODWORDS, *PTWODWORDS;/ In this example, only PSEARCH is redefined./ PFILE and PVOLUME will default to being defined as DWORDs./ You can define these types to be different types or the same type, based on your FSD needs.#define PSEARCH PTWODWORDS/ Now define the name of the file system.#define FSDAPI MyFSD#include 每个MyFSD.dll所提供的输出函式名称,都必须以档案系统驱动程序的名称为开头,在本例中为MyFSD_。不过也有特例,那就是FSD_MountDisk和FSD_UnmountDisk这两个函式,不必使用档案系统驱动程序的名称作为前缀。档案系统管理程序会检查这两个函式是否存在,来决定一个档案系统驱动程序是否合法。程序代码5.3说明了如何在模块定义档案 (.def) 中,定义MyFSD.dll所提供的函式。程序代码5.3 定义MyFSD.dll所提供函式的模块定义档案内容LIBRARYMyFSDDESCRIPTIONMy File System for Windows CEEXPORTSMyFSD_MountDiskMyFSD_UnmountDiskFSD_MountDisk=MyFSD_MountDiskFSD_UnmountDisk=MyFSD_UnmountDiskMyFSD_CreateDirectoryWMyFSD_RemoveDirectoryWMyFSD_GetFileAttributesWMyFSD_SetFileAttributesWMyFSD_DeleteFileWMyFSD_MoveFileWMyFSD_DeleteAndRenameFileWMyFSD_GetDiskFreeSpaceWMyFSD_NotifyMyFSD_RegisterFileSystemFunctionMyFSD_FindFirstFileWMyFSD_FindNextFileWMyFSD_FindCloseMyFSD_CreateFileWMyFSD_ReadFileMyFSD_ReadFileWithSeekMyFSD_WriteFileMyFSD_WriteFileWithSeekMyFSD_SetFilePointerMyFSD_GetFileSizeMyFSD_GetFileInformationByHandleMyFSD_FlushFileBuffersMyFSD_GetFileTimeMyFSD_SetFileTimeMyFSD_SetEndOfFileMyFSD_DeviceIOControlMyFSD_CloseFileMyFSD_CloseVolume这个我们假想的档案系统驱动程序MyFSD,提供了所有的档案系统函式,但是开发人员也可以在档案系统驱动程序中不提供某些输出函式。对于这些缺少的函式,档案系统管理程序将自动以回传ERROR_NOT_SUPPORTED的stub function代替。 档案系统驱动程序的加载当安装已注明使用某档案系统的外围储存装置时,该档案系统驱动程序会被自动加载。当外围储存装置加载系统时,储存管理程序会从注册信息中,读取与其相关的注册信息,其中定义了将要使用的档案系统驱动程序。在此我们仍假设该档案系统驱动程序为MyFSD。外围储存装置加载系统后,储存管理程序会从装置管理程序接收到一个通知,其中含有该装置的装置名称及其GUID等信息。其中,GUID的作用非常简单,透过检查装置的GUID,就可以确定新发现的装置是否为区块装置,因为只有区块装置才会用到档案系统。之后储存管理程序会根据从注册信息中得到的配置信息,为该装置加载合适的分割区驱动程序,并为每个分割区加载对应的档案系统。储存管理程序在加载档案系统驱动程序时,会检查MyFSD是否含有FSD_MountDisk和FSD_UnmountDisk这两个函式,只有找到了FSD_MountDisk和FSD_UnmountDisk,才能说明这是一个合法的档案系统驱动程序,也才会进行后续的工作。之后,档案系统管理程序会呼叫MyFSD.dll的函式FSD_MountDisk。FSD_MountDisk负责根据MBR (Master Boot Record) 中的DPT (Disk Partition Table),以及扩展分割区连结串行中的信息找到装置上所有的volume,并呼叫FSDMGR_RegisterVolume向档案系统管理程序注册每个volume。所有这些注册过的volume,就会以目录的形式显示出来,应用程序也可以透过档案系统函式对它们进行存取了,往后当使用者透过档案系统Win32 API对该volume上的档案进行存取时,档案系统管理程序就可以透过完整目录名称中的目录名称,找到对应的档案系统驱动程序了。与此类似,当档案系统驱动程序的输出函式MyFSD_UnmountDisk被呼叫时,装置上的所有volume会被注销。 档案系统管理程序的作用档案系统管理程序的功能是由Fsdmgr.dll这个模块提供的,它负责管理和沟通系统中所有可安装档案系统。档案句柄的建立、volume的注册、所有必需函式的安装、档案系统Win32 API到可安装档案系统输出函式的映像,所有这些都是由档案系统管理程序完成的。当应用程序存取某个volume上的目录和档案时,档案系统管理程序会负责呼叫相对应的档案系统输出函式。应用程序是透过档案系统Win32 API存取可安装档案系统的。例如,当应用程序要在装置上建立一个目录时,它会呼叫CreateDirectory函式。之后,再由档案系统管理程序将建立目录的工作,交由该装置所使用的档案系统驱动程序来完成。在开发档案系统驱动程序时,可以使用档案系统管理程序提供的下列函式: FSDMGR_CreateFileHandle FSDMGR_CreateSearchHandle FSDMGR_DeregisterVolume FSDMGR_GetDiskInfo FSDMGR_GetVolumeName FSDMGR_ReadDisk FSDMGR_ReadDiskEx FSDMGR_RegisterVolume FSDMGR_WriteDisk FSDMGR_WriteDiskEx 这些函式实作了档案系统驱动程序与操作系统和装置驱动程序的双重隔离。除了以上函式之外,Fsdmgr.dll也为 CreateFile和FindFirstFile这些函式提供了对应的函式。这些函式的原型都是在Fsdmgr.h中定义。5.2 实际分析5.2.1 概述对于任何新加载系统的外围储存装置而言,首先要做的就是将其纳入系统的管理,然后才使用该装置。从底层区块装置驱动程序的加载,到分割区驱动程序的加载,以及档案系统驱动程序的加载,最后得以将区块装置及其使用的各种驱动程序,纳入装置管理程序和储存管理程序的管理当中,这是一个由下而上的过程。而透过统一的档案系统Win32 API接口到对应的档案系统驱动程序,再经由分割区驱动程序或直接交给装置驱动程序,完成最后的档案操作,这则是一个由上而下的过程。前者就是将外围储存装置纳入系统管理的过程,后者则是对外围储存装置的使用过程,本段落的重点是分析将外围储存装置纳入系统管理的过程。当系统发现一个新的装置时,首先,装置管理程序会负责为其加载相对应的装置驱动程序,并在装置管理程序中建立相对应的数据结构,记录与该装置相关的各种信息。之后,如果发现新加载的装置是区块装置的话,还要由储存管理程序为其加载档案系统驱动程序。这时,装置管理程序会将一些重要的信息告知储存管理程序,由它来完成后面的工作。储存管理程序首先会根据注册信息中的配置信息,为区块装置加载分割区驱动程序,分割区驱动程序的主要作用就是定位区块装置上的分割区。储存管理程序会为装置加载所需的档案系统驱动程序。在这一过程中,储存管理程序会为装置上的volume,注册一级目录的入口项,将来使用者透过完整路径名称对档案进行存取时,就是由其中的一级目录名找到相对应的档案系统的。这一过程大致如下:1 装置管理程序负责加载区块装置的驱动程序,2 由该装置发出一个通知,告知储存管理程序该装置的装置名称及其GUID等信息,3 储存管理程序根据配置信息,为该装置加载分割区驱动程序,4 储存管理程序行举该装置上的所有分割区,5 储存管理程序为每个分割区加载档案系统驱动程序。下面我们先对这一过程中所使用到的数据结构做介绍,然后再详细讲说上述储存管理程序分层结构的建立过程,以Ramdisk的安装过程为例,看一看在实际的程序代码中这一过程是如何实作的。5.2.2 重要的数据结构每当系统中出现新的外围储存装置时,储存管理程序都会为其建立一系列的数据结构,用来维护与该装置有关的信息。这些数据结构包括CStore、DriverState和DSK等等,它们都是用来描述一个装置的。对于装置上的分割区,储存管理程序中也有一套用于维护分割区信息的数据结构,包括CPartition、PartState和VOL等等。CStore是一个类别,它描述了一个外围储存装置的一些基本信息,由储存管理程序负责建立,其中一些成员变量的含义如下: m_szDeviceName:装置名称,由装置管理程序告知; m_DeviceGuid:装置的GUID,也是由装置管理程序告知的; m_szRootRegKey:此装置的配置信息在注册信息中的位置; m_pPartDriver:装置所使用的分割区驱动程序; m_pPartitionList:装置上的CPartition分割区连结串行; m_dwStoreId:由分割区管理程序维护的与此装置对应的DriverState结构的指针; m_pNextStore:指向g_pStoreRoot队列中下一个CStore。DriverState由分割区管理程序负责建立并维护,记录了一些与分割区管理程序有关的装置细节信息,其中一些成员变量的含义如下: pPartState:装置上的PartState分割区连结串行; pSearchState:指向SearchState结构组成的连结串行; diskInfo:装置参数,包括CHS值、每个扇区所含的字节数等等; snExtPartSector:装置上扩展分割区的起始扇区; snExtPartEndSec:扩展分割区的结束扇区。CPartition也是一个类别,用于描述装置上的分割区,由储存管理程序负责建立并维护,其中一些成员变量的含义如下: m_dwPartitionId:由分割区管理程序维护,与此分割区对应的PartState的句柄; m_dwStoreId:与此分割区所在的装置对应的DriverState结构的指针; m_szPartitionName:分割区的名称; m_szFileSys:此分割区所使用的档案系统的名称; m_pDsk:指向由档案系统驱动程序负责维护,与此装置相关的DSK结构; m_hFSD:档案系统驱动程序对应的动态链接库的句柄; m_pNextPartition:指向同一装置上的下一个CPartition物件。PartState是分割区管理程序为维护分割区信息所使用的数据结构,与DriverState密切相关,其中一些成员变量的含义如下: cPartName:分割区的名称; snStartSector:该分割区的起始扇区号; snNumSectors:此分割区所占用的扇区数,即分割区大小; NextPartState:指向同一装置上的下一个PartState结构; pState:指向此分割区所属装置的DriverState结构。CPartDriver是一个类别,用于描述一个分割区驱动程序,其成员变量m_hPartDriver记录了该分割区驱动程序对应的动态链接库的句柄,其它的成员变量均为函式指针,一一对应于分割区驱动程序的输出函式。以上这些数据结构的关系如图5.4所示:图5.4 CStore, DriverState, CPartition, PartState, DriverState数据结构关系图下面再来看一下由档案系统管理程序建立并维护的FSD、DSK和VOL这三个数据结构。FSD结构用来描述一个档案系统驱动程序或是一个过滤器,其中一些成员变量的含义如下: hFSD:档案系统驱动程序或过滤器对应的动态链接库句柄; pfnMountDisk:指向档案系统驱动程序函式FSD_MountDisk的指标; pfnUnmountDisk:指向档案系统驱动程序函式FSD_UnmountDisk的指标; pfnHookVolume:指向过滤器函式FSD_HookVolume的指标; pfnUnhookVolume:指向过滤器函式FSD_ UnhookVolume的指标; szFile

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论