摘要:本文提出了基于ucos ii的一个文件系统的设计与实现方法。通过分析文件系统中的层次结构和功能模块,给出了文件系统的详细设计方案,包括文件控制块、文件描述符和文件保护机制等。最后还阐述了文件系统为保证可靠性所采取的技术。 1 前言 从系统的角度来看,一个文件系统要实现对存放文件的存储空间的组织、分配、信息的传输,并对已存储信息进行检索和保护等;从用户来的角度看,文件系统应该做到存取文件方便,信息存储安全可靠,既能实现共享又可做到保密。当用户要求文件系统保存一个已命的文件时,文件系统能将它们放在适当的地方。当用户要使用文件时,文件系统可以根据文件名找出某个具体文件。 文件系统设计时,必须遵循以下几个基本原则:第一简洁性,现有的比较完善的文件系统功能齐全、对系统资源要求较高,而我们所需要的这个嵌入式文件系统是嵌入式平台的一个中间件,要求简洁高效可靠。为此我们在设计过程中借鉴了MS-DOS的FAT16文件系统格式的目录形式进行文件管理,打开文件数据结构则采用了类似于UNIX系统文件表的方式,为每一个打开文件设置了一个数据结构指针FS_FILE,使得用户接口简洁明了。第二多设备驱动支持(多介质兼容),考虑到应用的广泛性和存储介质的多样性,要求我们在进行设计文件系统时必须考虑对多种存储介质的兼容性。整个系统采用模块化分层设计的原则和面向对象的实现方法,使得用户可以通过统一的顶层应用程序接口方便地对各种存储介质进行文件操作。利用本文件系统可以管理不同的存储介质,可以同时访问不同的硬件。第三多操作系统支持,文件系统的开发是基于ucos ii,在设计开发过程中,考虑到以后对多操作系统的支持,OS接口模块设计为动态可变,当文件系统应用于其它操作系统时,只需将OS接口模块中的操作系统信息变为新的操作系统即可。第四可靠性,由于嵌入式系统的数据资源的重要性,要求存储数据的物理介质必须具有很高的稳定性,可是我们知道一些人为或外在的因素可能会导致介质的损坏,从而造成数据的缺失,所以我们要尽可能提高文件系统可靠性。 2 文件系统的层次结构和功能模块 嵌入式文件系统由于功能和作用与普通桌面操作系统的文件系统不同,导致了二者在体系结构上具有很大的差异性。在普通桌面操作系统中,文件系统不仅要管理文件,提供文件系统调用API,还要管理各种设备,支持对设备和文件操作的一致性(即要象操作文件一样来操作各种I/O设备)。在嵌入式文件系统中,这种规则发生了很大的变化。在某些情况下,嵌入式系统可以针对特殊的目的来进行定制,特别是随着ASOS(Application Specific Operating Systems,为应用定制的嵌入式操作系统)的发展,对嵌入式操作系统的系统功能规整性、可伸缩性及其灵活性提出了更高的要求。 基于以上的考虑,我们采用了如图1所示的嵌入式文件系统体系结构,该结构定义的文件系统从上到下有三个层次:第一层为API层、第二层为中间转换层、下层为介质驱动层。第一API层:API层是文件系统和用户应用程序之间的接口,它有一个标准C函数库,其中包含有诸如打开文件(FS_FOPEN)、写文件(FS_FWRITE)等函数。本层的功能是将用户调用传送给中间转换层。这是整个系统设计的核心,也是嵌入式文件系统中用户唯一可见的部分—— POSIX中文件系统的标准系统调用全部在该部分中得以实现。第二中间转换层:中间转换层要为文件系统的实现提供与硬件无关的统一接口,是文件系统结构规整性的基础。中间转换层包含有文件系统子层及逻辑块子层,其中文件系统子层将文件操作解释到逻辑块子层,然后文件系统调用逻辑块子层并根据不同的设备定义出相应的设备驱动程序;逻辑块子层主要是同步对设备驱动程序的访问,向上提供友好界面。第三介质驱动层:介质驱动层是访问硬件的最低端的程序,该程序的结构要能够便于实现对硬件的访问。本层的功能主要是完成对介质的访问。本层的重要任务就是提供统一的设备驱动程序接口。 根据文件系统的层次结构,可以将该文件系统分成四大功能块:API接口模块、中间转换模块、磁盘分区模块、设备驱动模块。其中API接口模块主要完成文件的基本操作,包含有文件的生成、删除、打开、关闭、文件读、文件写等。中间转换模块主要完成对存取权限的检查、介质的选择、逻辑到物理的转换。磁盘分区模块主要完成对几个主要数据结构的初始化,设置文件系统的总体分区信息以及每个分区的几部分:空闲块管理、引导区、FAT区、文件存储区等。设备驱动模块完成存储介质的驱动程序,包含有一个驱动程序函数表和介质读、介质写、检查状态、执行特定命令等驱动程序。 3 文件系统的详细设计 3.1文件系统组织方式 文件系统逻辑组织为流式文件,物理组织为连续文件。用户对于流式文件的访问是以字节为单位的。每个文件的内部有一个读写指针,通过系统调用可以将该指针固定到文件的某一个位置处,以后的读写系统调用将从该指针所确定的位置处开始。而用于保存文件的物理设备是划分为块页的,文件的物理结构就是要确定如何将字节保存在存储介质中。所以说文件的物理组织形式对于文件系统的性能有着较为直接的影响,所以我们在进行文件的物理组织选择时比较慎重。结合我们系统的实际应用情况,我们决定文件的物理组织方式采用顺序结构,这是因为我们的嵌入式应用环境要求实时性高,采集到的数据一旦以文件的方式存储在介质上很少进行改动,也即文件的长度变化不大,所以我们将逻辑文件的信息存放在外存的连续编号的物理块中。 3.2文件和文件控制块FCB 为了实现对于文件的管理,系统需要掌握一组有关文件的描述信息,例如文件的名称、文件的地址、文件的建立曰期等等,这些信息组合在一起构成一个数据结构,在这里我们称之为文件控制块FCB(File Control Block)。FCB是文件存在的标志,其中记录着系统对于文件进行管理所需要的全部信息,FCB所包含内容如图2所示。每一个文件都有一个文件控制块,它们被保存于外存空间,当系统欲访问一个文件时,应当能够根据文件名字找到它所对应的文件控制块,然后根据文件控制块中的文件位置信息找到该文件具体所存放的区域。 3.3文件描述符 文件描述符由基本文件名和扩展文件名两部分构成,二者以圆点分开。文件名由1-8个字符构成,扩展名由1-3个字符构成。分别占据FCB中的00H- 07H和08H-0AH两部分。在FCB中,文件名和扩展名是左对齐放置的,剩余部分填入空格码。当进行文件删除时,在文件目录记录项的第一字节中放入 E5H,表示该记录项是空项。从公平没有使用过的记录项的第一字节中写入的是00H,刚刚格式化的根文件目录或刚刚生成的子文件目录的未使用文件目录记录项的开头写入的均是00H。这个00H在文件进行检索时特别有用,主要是用来确定搜索到文件目录的什么区域就可以不用再继续搜索了。例如,当文件检索中没有00H时,必须对全文件目录区进行检索,而一旦遇到有00H的场合,检索便宣告结束,这样可以大大缩短检索文件的时间,提高了文件检索的效率。 3.4对文件的主要操作 文件系统的功能是通过一系列对文件的操作实现的。为此,系统提供给用户一整套系统调用,用以完成创建、打开、读、写、关闭、删除文件等项工作。对应的函数分别为:FS_FOPEN()、FS_REMOVE()、FS_FCLOSE()、FS_FREAD()和FS_FWRITE(),各函数均通过驱动模块来实现,具体的代码此处不在罗列。 3.5文件的保护机制 由于文件系统保存着用户非常重要的信息,因而如何保护信息、防止未授权使用就是所有文件系统必须要解决的重要问题之一。但系统中的全部信息又不能完全成为私有,还必须进行文件共享,以提高资源的利用率和方便用户使用。 文件共享和保密是一个问题的两个方面。对文件的保护保密是由对文件的共享要求起的。在非共享环境中,不需要再做什么保护,实际上它已经是极端的完全保护情况;相反,另一种极端情况则是完成共享,而不做任何保护。这两种情况都缺乏实用意义,一般用法是有控制的进行文件共享。保护机制通过限制文件的存取类型来实现受控制共享。允许或禁止对文件的存取受多种因素的限制,如用户的身份、文件本身的性质、对文件所要进行的存取类型等。常用的保护机制有命名、口令、存取控制、密码等,对文件的保护必须要根据实际需要和实现的可能性来选择合适的方法。由于本文件系统主要是以FAT文件系统为基础来进行设计的,所以在对文件进行保护和共享方面同样也有FAT文件系统所具有的不足,没有一套完整的文件保护机制来完成对文件的保护,安全特性只能通过共享权限来加以实现。 4、文件系统的可靠性设计 对文件的可靠性设计主要从三个方面处理:FAT表保护、存储介质坏区的检测与处理、数据校验。在整个文件系统的安全性上,FAT表是重中之重,需要采取特别的维护,因为如果FAT表出错,则整个系统都将崩溃。为了防止出现系统瘫痪,我们对FAT表进行了备份。当出现非正常关机的时候,重新开机以后就要进行FAT表的校验。首先我们进行主FAT表的校验,如果主FAT表校验无误,则校验两个备份的FAT表,若均没有错误,则不做任何工作;若发现有错误的 FAT表存在,则用正确的FAT表将错误的覆盖;若主FAT表有误,而存在有正确的备份FAT表,则用备份的FAT表将主FAT表覆盖;如果主FAT表有误,而备份的FAT表也不正确,则宣告FAT表崩溃。此时只能重新进行分区。 此外,由于存储介质的使用寿命有限,所以我们在设计文件系统时一直本着尽可能少的对介质直接进行读写的原则。具体做法是在内存中建立FAT表的一个映射,在文件系统起动时将FAT表读入内存。这样,上层操作时如果涉及到对FAT表的更改,一般都先在内存FAT表映射中进行,不用涉及到介质的操作。我们通过设置一个更新标志来确定更新时机,首次将存储介质内的FAT表读入内存时初始化该标志为假,一旦操作中生成了新的文件项或释放块而需要修改FAT表项时,即置该标志为真。同时我们设置一个定时器来确定更新介质上的FAT表的时间,定时器每隔一定时间来检验更新标志,如果标志为真则将FAT表写入介质 FAT表。当然,在关闭文件时,无论定时器是否到时,都要进行上述检验更新。通过这样的设计,我们就可以大大减少了对存储介质上的FAT表的更新次数,也就达到了处长设备使用寿命的目的。 由于存储介质的寿命问题,随着时间的增长和使用次数的增加,个别区域会出现文件的写入读出错误,所以我们在设计文件系统时也考虑到了坏区的检验与管理。检验某一页是否损坏的方法是:将数据写入某页后立即读出,如果读出的数据跟写入的不一致,则说明该页为坏页。对于检验到的坏页,在空闲块管理区中进行标记,以后进行存储区域分配时不分配这些坏页,这相当于把坏页从空闲块中删除,只要不对坏页进行读写操作,文件系统就不会出现任何问题。 为了保证FAT表的可靠性,引入了校验和机制。同样,我们在进行文件系统设计时,通过在一个小区段内设置校验和来提高数据的可靠性。在每一页的最后4 个字节作为本页的校验和,该校验和的值是对本页数据的累加值。每次页操作时都要在更改数据的同时重新计算校验和。如果发生非正常关机等意外情况,则开机后,下一次对该页操作时可通过比较保存的校验和与各项重新累加计算出来的校验和来检查该页数据是否出错。 5、结束语 嵌入式系统的开发是后PC时代的一个潮流,各种嵌入式操作系统也是为争夺这一片空间而绞尽脑汁,公开源代码这个特性注定了ucos ii非常适合于嵌入式系统。开放源码导致了定制的方便,开发人员可以从多个软件中提取需要的精华,应用到自己的应用中去,从而大大节省开发成本,缩短研发周期。本文所设计的文件系统正是利用了ucos ii的这些特点,做到了高效、方便、易于维护、易于移植,并且系统资源占用率低,充分体现了嵌入式中间件的特色,极大的方便了用户的使用。
|