0 引言
在vxworks的应用系统中,基于flash的文件系统通常都采用dos+fat+ftl的结构。
一般情况下,磁盘文件系统大多是基于sector的文件系统,磁盘按照物理上分为柱面、磁盘、扇区,扇区是基于块的文件系统操作的基本存储单位,磁盘的容量都是根据这些数据计算出来的,每个扇区大小通常都是512bytes。
vxworks文件系统中的dosfs是ms-dos兼容的文件系统,可基于块对物理介质进行操作。由于fish的物理特性,对flash作基于块(不同于flash的擦除块)的操作必须由软件作封装实现,这就是tffs所起的作用。
1 vxworks文件系统的总体结构
vxworks文件系统的总体结构以及tffs在整个文件系统的位置如图l所示。
tomado下的tffs文件系统是tornado的一个可选组件,它可为种类繁多的flash设备提供一个统一的块设备接口。在tornado2.2版本中自带的tffs版本为2.0,在文件系统中,tffs的功能相当于磁盘驱动,通过tffs可使上层的dosfs或rtll文件系统像操作普通的标准磁盘一样来操作flash。
2 tffs文件系统的分层
图2所示为tffs文件系统的分层图。图中的core layer内核层可将其他层连接起来协同工作;翻译层主要实现dos和tffs之间的交互、管理文件系统和flash各个物理块的关系,同时支持tffs的各种功能,如磨损均衡、错误恢复等;mtd层执行底层的程序驱动(map、read、write、erase等);socket层的名称来源于可以插拔的socket存储卡,主要提供与具体的硬件板相关的驱动。
3 ftl层分析
ftl是tffs文件系统的核心,它是pcmcis的一项标准,意思是flash translation laycr specification,这种类型的文件系统是目前嵌入式系统中最流行的,很多公司都提供这种文件系统的相关解决方案。
ptl为dos bpb/fat与flash之间的中间层,ftl利用现成的基于块的文件系统(例如dosfs)来实现应用层的操作,实质上就是在flash设备上模拟磁盘块设备的实现,为基于块的文件系统提供统一的接口。ftl通过以下几步来模拟磁盘驱动:首先是在flash擦除块之外定义小的读写块(相当于磁盘扇区);其次是逻辑扇区(对块文件系统如dosfs呈现的地址)和物理地址(flash的实际地址)之间的转换;然后管理flash,使得能在空闲的地方写入数据。其核心就是将dos上的扇区映射到flash上去。
为了实现dos层从逻辑上看扇区是连续的,可随时对任意bit读写操作,ftl必须提供对flash芯片的管理,包括向上层(dos层)提供可以任意读写的操作接口,向下对flash的擦除、写入、读取统一管理,同时还必须提供磨损均衡,以防止一个擦除块提前损坏。
3.1 ftl的启动过程分析
在我们调用函数tffsdevcreate创建tffs文件系统时,会以参数fl_mount_volume调用函数flcall→mountvolume→flmount→mountftl,函数mountftl是ftl层的加载函数人口,处理过程首先是初始化ftl,然后就可按下列步骤进行:
(1)查找第一个合法的unit头信息
合法性的判断依据是unit header头上的标志cisf..ftl100和部分头部的flag信息,由于bsp已把fs的相关信息注册到ftl的数据结构中,所以,ftl层可以找到第一块unit,并可以向后查,直到找到合法的unit为止。
(2)检验信息合法性
将所有有用的信息都读出到内部数据结构中后,即可检验信息合法性。由于unit header中的unit id和擦除次数都相同,所以整个文件系统的共用信息都可以从首先找到的头中读出来。
(3)给mount每一个unit建立page表
这是mount最重要的过程,对每个unit调用mountunit()函数,并在mountunit()函数中首先判断,如果是非法unit,则作为交换unit,然后对每个bam选项进行处理,并对垃圾bam、空闲bam进行统计,如果是缓冲的bam数据和交换page的vbm,则将此page的逻辑扇区信息记录到内存的page表中,以便后续映射访问查询使用,而对于非缓冲的bam数据,则不作处理,另外,对于交换page的vbm,则进行记录。考虑到上述过程,可见其系统中的page vbm和缓冲的数据bam分布在各个unit的各个角落,需要将所有的vbm和缓冲数据bam收集起来建立整个交换page表,这是ftl标准层设计时就要决定的。
(4)检验逻辑unit的完整性
当所有的unit都mount完成后,每个逻辑unit都应存在,否则mount失败。
(5)判断并关闭交换page
如果系统中已存在交换page,则对系统中存在的交换page进行关闭操作,以便后面检查page的完整性。
(6)检查page的完整性
系统中的page表必须是完整的,这个表中包含有缓冲的数据bam映射信息和更重要的page映射信息,因此,缺少任何一个,都将导致dos的虚拟扇区无法映射到相应的逻辑扇区。
从上述过程可见,整个mount过程是将文件系统信息读入内存数据结构并检验的过程,这个mount ptl过程完成后,mountvolume ()函数即将隐蔽的0扇区和dos的启动扇区信息读入内存数据结构,这样,dos就可以访问ftl底层扇区了。
3.2 tffs的块映射
图3中,ftl层将dos上连续的扇区映射到flash上某个r/w block块中,同时在某个位置记录一个映射表(称为map表),该表中记录了dos的扇区映射到flash中的哪个block,当dos要进行读操作时,ftl首先查询这个map,以获得映射信息,然后读取相应的block信息并返回给dos,从而实现读映射。当dos需要写入操作时,可能存在将bit0修改为1的情况,于是ftl层将申请一个新的block块,并将新信息写入,然后修改map信息,记录这个dos扇区已经重新映射了,从而实现写映射。所以,从逻辑上看,ftl层就实现了dos扇区的映射和flash的写入管理。
3.3 垃圾收集过程
ftl格式化后,可用扇区将被不断申请使用,原有扇区被不断的废弃,系统中可用的free扇区越来越少,但这并不是由于上层dos真的使用了这么多扇区,而是ftl为了方便管理、为了不需要每次擦除一块而付出的管理代价。所以,当系统中的可用扇区少于用户要申请写入的扇区时,ftl层就必须解决这些垃圾问题,这个过程在ftl中称为垃圾回收(garbage collect)。
当ftl中的可用sector小于用户要申请的扇区时,系统将启动垃圾收集,但系统中有很多个unit,到底收集哪个unit呢?ftl会考虑磨损均衡,它将采用一个伪随机的算法来决定收集策略:即用4/256的几率选择磨损情况少的块来收集;252/256的几率则根据垃圾最多为第一条件,当垃圾一样时,判断磨损次数小的优先选择。
3.4 ffl创建的dos
tffs的格式化函数需要调用tffsdevformat来格式化,而不需要调用dosfsvolformat来格式化;另外,在tffsdevformat格式化参数中,需要传人的参数含有fat个数参数,其原因是dos是ftl层创建的,而不是在ftl基础上创建的,下面是tffs的整个格式化过程:
tffsdevformat→flcall(fl_format_volume)→formatvolume→format→formatftl;
其中,函数formatftl是执行ftl层格式化的操作函数,操作时,首先根据格式化参数和bsp参数对内部数据结构初始化;然后再对每个unit进行格式化,在擦除后,即可写入unitheader信息和控制bam值;之后写入unit no;最后申请每个page的空间;
上述formatftl函数执行完以后,ftl就已经准备好,可以接受上层的扇区读写函数了(当然还没有内容可以读写)。
在函数formatvolume中,mount可进行卷操作,当内存的数据结构准备好后,ftl层即可调用函数fldosformat来创建dos。其中首先创建隐藏扇区,以用于记录该卷的部分信息,然后分别创建mbr、fat和root目录;这样,dos创建完成后,再执行dosfsdevcreat函数,当然就无须格式化,找到0扇区自然就找到了mbr,因为dos是ftl创建的。
从更深层次讲,ftl层之所以创建dos层,是因为只有ftl层才知道有哪些扇区是可以供dos使用的,哪些扇区是dos不能使用的(作为ftl层管理使用),也正是因为dos层不了解ftl层的运作情况,所有的扇区映射关系都被ftl层隐蔽,因而导致dos层无法在上层作出有利于flash擦写等优化动作,如大文件写入时的字节数更新,fat表更新等操作,都会严重浪费ftl层的映射关系运算。
4 基于m25p32 spi flash的tffs设计
对于tffs的实现,涉及到config.h、systffs.c、tffsconifg.c、tffsmtd.c、makefile几个文件的配置和修改,其中编译是通过建立一个downloadalbe的tomado工程,来把这几个.c源文件编译进去生成.pl文件提供给bsp工程,而后由bsp工程把.pl文件编译进去,从而生成bootable image。
4.1 config.h的相关配置
要在vxworks映像中加入tffs文件系统,需要加入相关的组件,虽然也可以在该文件中直接加入相应的配置宏,但很容易造成遗漏和有些需要依赖的宏没有定义或者冲突,本文采用的方法是建一个bootable的tornado工程,而后在这个工程中通过加入tffs和dosfs的相关组件来编译这个工程,从而生成一个prjparams.h文件,该文件里就包含了刚刚加入的组件对应的宏,因而,组件与组件之间依赖也是安全的,不会有任何冲突,最后再在config.h中包含这个文件即可。
4.2 systffs.c文件的修改
该文件用于提供socket层的bsp实现代码。如果镜像文件包含tffs相关组件,那么,系统启动时就会按照如下过程自动调用systffsinit()函数:
usrroot()→tffsdrv()→flinit()→flregistercomponent ()→systffslnit ()
systffsinit ()函数会依次调用socket注册函数simmregisterofsl (),注册函数数量视需要构建的文件系统数量而定,本文构建了1个文件系统ofsl,并在simmregisterofsl()函数中对文件系统的基地址进行了设置,同时对flsocket()结构体中的毁掉处理函数进行了挂接,挂接函数也在该文件中实现,如卡上电、断电、写保护等。
对systffsformaofsl()函数的格式化参数可根据自己的需要进行修改。
4.3 tffsconfig.c和tffsmtd.c文件的修改
tffsconfig.c文件的修改就是在mtdtalbe []表中注册flash识别函数iunifiedidentifyofsl();而tffsconfig.c文件则用于实现iunifiedldentifyofsl()函数,iunifiedidentifyofsl()函数对flflash结构体中的回调函数进行了挂接,如flash的读、写、擦除等,挂接函数的具体实现可在dry_mvsflash.cpp文件中以一个类的方式提供针对m25p32 spi flash操作的所有驱动接口。
4.4 tffs文件系统的安装
通过上面的过程,socket层和mtd层就都准备好了,下面便可以安装tffs文件系统。安装时,首先用systffsformatofsl()函数按照上面设定的参数格式化tffs文件系统,而后通过usrtffsconfig(0,0,”ofsl”)函数接口在已建好的tffs上挂接dos文件系统,成功后,即可通过open、read、write等来操作flash上的文件系统,也可以通过ftp方式用ie访问该文件系统中的内容。
4.5 makefile文件的修改
对于makefile的修改非常简单,因为几个和tffs相关的源文件都是以.pl的方式被链人bsp工程的,所以只需要在makefile文件中把这个文件加入即可,即在makefile中加了如下的宏定义:
mach_extra+=../armpri/armarch5gnu/armbspprj.pl
5 结束语
本文对vxworks下tffs文件系统的层次结构和ftl层的启动过程、块映射算法、垃圾回收算法以及用ftl创建dosfs进行了分析,给出了在m25p32 spi flash上创建tffs文件系统和将tffs挂在dosfs的实现方法。通过对tffs核心层fil的分析给出的tffs实现方法,可以从更基础的层面来认识vxworks中的tffs文件系统,从而给tffs文件系统的问题定位和实现带来新的方法。
热电偶补偿导线的原理及作用
华为P10最新消息:华为P10继疏油层、内存门、闪存门之后爆出断流门?断流门系造谣已通过技术分析
详解开关电源的三大基础拓扑
光电传感器的组成及分类
我的家里不能有草原,但是我可以有华为p10草木绿!
VxWorks文件系统、Flash的TFFS设计与实现
西门子PLC的公共变量与局部变量
电位器如何维修?
半导体生产过程有这么多设备
TNG成立了新的子公司TNG Energy,以制造钒电池
在LabVIEW中调用OpenVINO™ 模型
Linux开发_文件目录操作介绍、创建BMP图片
简单上云第一步的华为云服务器,助力中小企业提升业务
百度Apollo2.5全球首发:比亚迪成第100位合作伙伴,进一步提升自动驾驶安全性
龙芯3A5000高端控制器亮相第13届中国国际机器人高峰论坛
miui和flyme是国产最强系统?
借壳上市后的三盛控股正全力冲刺 营收猛增未来可期
绿牌油车豪曼冷藏版 续航将不再是问题
Autopilot的识别堆栈内深挖细品
元宇宙为何吸引资本压重注