东南大学硕士学位论文
4.1.2在flash上建立文件系统
针对嵌入式系统的应用环境以及FIAsH芯片的特性,对文件系统一般有如下要求:一是掉电安 全(cfash^)0、Ⅳcrdown—safc),嵌入式系统的运行环境一般比较恶劣,但同时又要求有比较高的可靠性, 这就对FLAsH文件系统提出了较高的要求,无论程序崩溃或系统掉电,都不能影响文件系统的一 致性和完整性,文件系统的写入,垃圾回收等操作对系统异常终止都非常敏感,极易造成数据丢失 和数据垃圾。二是平均使用(we廿Icvding),如上所述,FIAsH扇区的擦除次数都有限制,文件系 oll∞don),任何存储器在分配使用一段时间之后,都会 的使用寿命。三是高效垃圾回收(garbagec出现空区和碎片数据,这就需要进行垃圾回收,以保证存储器空间的高效使用。而FL.~sH擦除以扇 区为单位,垃圾的回收也应以扇区为单位,先移动扇区数据。再擦除整个扇区。四是低空间消耗(10w
统对HASH的使用必须充分地考虑该特性,最好能均匀使用FLAsH的每个扇区,以延长卧sH
ov盯11ead)。o耐Iead指文件系统管理结构在FIASH存储器上的空问消耗,这部分空间用于文件系
统建立,而不能用于实际数据的存储,因为,一般嵌入式系统中存储器空间有限,低空间消耗可以
提高有用数据的存储空问。
针对上述对文件系统的要求,如何实现嵌入式flash文件系统呢?这其中有三种常用方式:一 是集中管理式文件系统,现在的台式机器使用的大多属于这种类型,其主要特点是存储器空间的使 用信息集中存放在存储器的某个地方,而这个关键的信息区如果损坏,则文件系统将无法恢复.如 果在FLASH上使用这种文件系统需要大量的R.^M空间作为FLAsH的更新缓存,这类文件系统在掉电 安全上有明显的缺陷:二是线性文件系统,又称连续存放文件系统,每个相关的所有信息都连续存 放在存储器中,与集中管理式文件系统相比较而言,实现更简单,读写更快速,更重要的是将文件 系统的关键信息分布存放,这种文件系统更适合用于FLASH存储器.但对文件的操作效率很低,不
S),这种文件系统顺序 容易实现添加.插入,剪切等操作;三是日志文件系统(Log—StnlcturedF
写入对文件系统的修改.就象做日志记录一样,可加速文件写入和崩溃恢复。本文接下来将重点讨 论这种文件系统。
4.2 JFFS文件系统
4.2.1 JFFS的特点
JFFs是由瑞典的AxIs通信公司开发的文件系统,是专门针对无盘嵌入式系统中FLAsH存储器 而设计,由于其遵循GPL开放源码,所以很容易利用其思路进行移植工作。目前已经有了JFFS的第 2个版本即JFFS2,新版本主要改善了存取策略以提高FLAsH的抗疲劳性及优化了碎片整理性能,
增加了数据压缩功能。
下面来看JFFS是如何来满足前面提到的对基于FLASH存储器的嵌入式文件系统的要求:为了保 证文件系统在任何情况下都是安全,完整和一致的,JFFS使用了日志方式,即LOG结构的文件系统: 为了保证FLASH空间不溢出,JFFS提供了有效的垃圾回收功能,即在FLASH上创建JFFs文件系统 后,经过一些修改和操作,就会出现不在使用的数据区。称为脏区,当脏区超过一定数量后就必须
F进行垃圾回收操作了,顺序是从前到后,即前面的先清除;为了保证存储器的平均使用率。JFS具
有疲劳均匀(war—leveling)的特性,JFFS就像一个循环文件:在末端写入,始端进行擦除或垃 圾收集,而可在任意位置进行读操作,这样对存储器空间的来说也是一种循环使用方式。
4.2.2 JFFs的结构分析
下面简单介绍一下JFFS文件系统的结构设计,以JFFS2的版本为例
22
苎婴童!型竺:!堕奎堡墨竺婴!
在存储格式上,JFFS2是以Log-Stnlctured为基础的日志式的,日志的组成单位是存储节点,
每个存储节点与一个inode相关联,inode是JFFS2文件系统的基本组成构件,每个文件或目录(看 成特殊的文件)都有且只有一个inode描述,因此inode的编号是唯一的。
——一污瓣区毽豳 有敢区[=]空白区
图4.1 JFFs文件系统结构图 如上图所示.各个文件的存储节点按
照建立的时间先后.顺序地存储在F1ash上.并且在可利
用的存储空间里严格地按线性增长。存储空间由若干擦写块组成,各个擦写块之间相互独立,存储节 点不能超越擦写块的边界存放。在JFFSl文件系统中存储节点类型只有一种。JFFS2文件系统支持 的存储节点类型较前者要丰富。JFFs2沿用了ext2文件系统中兼容位码的方法.允许用户为系统定 义新的节点类型。所有类型的节点都有一个通用头部,头部包含了节点的类型、长度、头部CRc校 验位等信息。节点类型字段的最高两位有特殊含义.它的取值代表着当内核不支持当前节点类型时 应该采取的操作,它们是;(1)JFFs2一FE^11艇卜INc0好AT:拒绝安装该文件系统;(2)JFFS2一
FE删RE_R0c0MPAT:以只读方式安装文件系统;(3)JFFS2一FE删RE_Rwcojl2PAT-DELETE:以读写方
式安装文件系统,当回收废弃块时,删除该节点:(4)JFFS2一FE^11瓜E-R删PAT_c0PY:以读写方
式安装文件系统,当回收废弃块时,要将该节点完好无损地复制到新的存储空间中。
在JFFS2文件系统中定义了3种具体的节点类型。 (1)JFFS2_NODETYPE—INODE:这种节点用于存储普通文件的数据,在节点的起始位置存放着所
ffs2一raW-inode结 属文件的系统信息,随后是文件的有效数据。系统信息的存储格式由struct j构给出(定义在jffs2.h文件中,位于标准Linux内核源代码目录中),其主要属性如下。1)ino: 节点所属文件的inode编号;2)version、Ⅲode:存储节点版本号、文件模式;3)uid、gid:文件 属主id、所属组id;4)atime、mtime、ctime:3种时间戳,分别表示最后访问时间、最后更新时 间和创建时间;5)dsize,csize:所含数据压缩前和压缩后的大小;6)data_crc、node_crc:数 据校验位、节点校验位。每个节点都有个版本号(version字段).同一inode的存储节点版本号之 间存在升序的关系。新节点的版本号总是不小于旧节点的版本号。如果旧节点包含的数据被新节点 覆盖,该旧节点将被标为作废节点。作废节点占有的存储空间称为“污染空间”,是可以被回收再次 利用。存储节点的数据可以被压缩存储,为了加快读取整个页面数据的解压缩速度,系统规定每个 节点的数据不能超过所在硬件平台的页面值。
一 rffs2(2)JFFS2-NODErYPE_DIRENT:这种节点用于存储目录文件或inode链接符。stnlctja'
rdirent结构给出了它的定义(在jffs2.h中定义)。具体属性如下。1)pino、ino:父inode号、 所属inode号;2)ver2sion:本节点版本号;3)nsize、n∞e:文件名长度和文件名;4)node—crc、 name—crc:节点校验位、名字校验位。删除文件链接操作是通过写一个新的同名目录节点到存储介 质上,并置ino字段‘O’值实现的:而改名操作JFFS2系统则分为两步实现:第一步是用新的名字 和老inode号生成一个新的目录节点,产生一个新的链接。第二步用老名字生成一个inode号为‘0’ 的目录节点来断开原来的链接。这样在改名过程中系统可以通过新老两个链接名访问目标节点,这
0rtable O种策略符合POSIx(ThePperating Syst∞Interface)规范的要求。
东南大学硕士学位论文
(3)TFFS2一NODETYPE—CLE^瑚^RKER:当成功回收了一个擦除块后,系统将在该擦写块上生成一 个这种节点,用于表明这个擦除块是可以安全使用的。
在理解JFFS2存储格式的基础上。接下来进一步讨论JFFS2文件系统重建操作。和其他的Linux文 件系统一样,JFFS2在系统启动的时候要向VFS注册,并在内存中建立完整的文件系统存储镜像。 但是启动结束后JFFS2文件系统并不是一直把所有的系统信息保存在内存,只局限于那些不易被快 速建立的信息。JFFS2系统的内存镜像主要通过两个数据结构来实现,它们分别是struct ffs2一inode—cache和stnlct jffs2一r卿1lode_ref。
砒r—ct
J他鼍哪n甜e..n订
U嚏tI刚fIag
图4.2 jffs2-rM—-nodeJef
如上图所示,jffs2一inode—cache是inode在内存中用于快速索引的数据结构.其中包含的信
息有:所属inode编号、该inode的物理存储块链表指针、inode的关联数。jffs2一rawllode—ref 是物理存储块在内存中索引结构,主要属性有:(1)next—phys:指向本擦写块下个存储节点的内存 索引块的指针;(2)next—in—ino:指向本inode的下一个存储节点的内存索引块的指针;(3) flashoffset:物理偏移地址。由于存储节点大小是4的倍数,所以该字段的最后两个数据位有特殊 意思,第l位保留待用,第0位用于表示本节点是否被废弃;(4)totlen:节点长度。JFFS2文件系 统的内存镜像建立工作是由函数jffs2一bu订d-filesystem()来完成的,其流程如下:(1)调用 jffs2一scan-mediⅧ(),扫描所有擦写块,将擦写块按类型插入到相应的链表中去.建立inode和 各种存储节点的缓冲链表;(2)扫描整个目录树,计算每个目录节点的关联数。建立每个inode与 其物理存储节点间的关联;(3)扫描所有链接数为0的inode节点并移除它们;(4)重新扫描一遍 文件系统镜像,删除暂时的文件系统镜像数据。
4.3枷m
我们知道,在做JFFS文件系统的具体应用实现时,并不一定需要了解J11毽本身的结构的实现, 只需要知道针对不同厂家,不同的型号的nash的接口,也就是JFFS是如何驱动(或者说是操作) FLAsH的。以JFFS2为例,JFf毽2对FLASH芯片的访问控制,如读写擦除操作等,都是调用MID 驱动来实现的,所以在实现JFFS2文件系统前,必须先了解一下什么是M1D。
MID(n1%lory慨llnologydcvice内存技术设备)是用于访问memory设各(I∞M、nash)的Lj肌x
的子系统。MTD的主要目的是为了使新的存储设备的驱动更加简单,为此,它在硬件和上层之间提
第四章ucLj叭x下的文件系统JFFs2
供了~个抽象的接口。MID的所有源代码在,d心re璐佃td子目录下。 可以将cFI接口的MTD设备分
为四层(从设备节点直到底层硬件驱动),这四层从上到下依次 是:设备节点、MTD设备层、 ̄frD原始设备层和硬件驱动层。
翳艮文件系统一|
陂件系掣和i l宇符设备节点一j
I块设备节点一l
l M
rD字犄设备一 |
MTD块设备p
I
MrD原始设备p
l
FLAsH硬件驱动p
图4’3 MTD结构图
l、F1ash硬件驱动层:硬件驱动层负责在i血时驱动Fl∞h硬件,uⅡ“MID设备的NoR Fl∞h 芯片驱动遵循c眄接口标准,其驱动程序位于drjvcn细td,ch袖子目录下。№悄D型F1∞h的驱动程序则位于,d巾reB,m旧『n∞d子目录下。
2、MTD原始设备:原始设备层有两部分组成,一部分是MID原始设备的通用代码,另一部 分是各个特定的只站h的数据,例如分区。用于描述MID原始设备的数据结构是mtd jDfo.这其中 定义了大量的关于MTDr的数据和操作函数。Ⅲ嗵_缸blc(m妯∞∞.c)则是所有MrD原始设备的列表, m
td._part(m嗵_pan.c)是用于表示MID原始设备分区的结构,其中包含了D埘iD如,因为每一个分
区都是被看成一个MTDc原始设备加在Ⅲ坩tr中获得。在driveB,mablted中的,删岫a,Ⅲap“子目录下存放的是特定的nrLmtdinf0中的大部分数据都从该分 区的主分区删山a小>mt髂h的数据,每
一个文件都描述了一块板子上的nash。其中调用addm衄d“iceO、dd mtd出vicco建立/删除mtdinf0结构并将其加~删除mtd诅ble(或者调用addmtdpam皿nO、delmtdparIi曲n0(mtdpaft.c)建立删除In嗵_part结构并将mtdpart如叫info加入删除mmIable中)。
3、MTD设各层:基于MID原始设备,linux系统可以定义出M’ID的块设备(主设备号31)
和字符设备(设备号90)。MTD字符设备的定义在Intdchar.c中实现,通过注册一系列趾opem60n
函数(1seek、叩∞、close、r∞d、wfb)。MTD块设备则是定义了一个描述MrD块设备的结构 mtdblk_dcv,并声明了一个名为Ⅲhlblks的指针数组,这数组中的每一个lmdbll【-dev和Ⅲcd切ble中 的每一个mtd inf0一一对应。
4、设备节点:通过Inknod在,dev子目录下建立MTD字符设备节点(主设备号为90)和MrD 块设备节点(主设备号为31),通过访问此设备节点即可访问hfrD字符设备和块设备。
2作为文件系统,则要将JFFS2的文件系统映像j凰.imc(或
j凰2.i
5、根文件系统:如果要将JFFS gmg)烧到n鹊h的某一个分区中,在觚M日n,Ⅲ∞h-yo删缸h.c文件的your_丘】【叩函数中将该分
区作为根文件系统挂载。
mounl6p、文件系统:内核启动后,通过Ⅻt姐上。
命令可以将Ⅱ∞h中的其余分区作为文件系统挂载到
简单地来讲,Mm可以理解为凡AsH的设备驱动程序,其主要向上提供两个接口,MID字符
设备和M’ID块设备。通过这两个接口,就可以象读写普通文件一样对FLASH设备进行读写操作。
经过简单的配置后,M1D在系统启动以后可以自动识别支持衄或JE珊'c接口的FLAsH芯片,
东南大学硕士学位论文
并自动采用适当的命令参数对FLAsH进行读写或擦除。同样也没有必要去细究M1D的具体实现代
码。
4.4JFFs2的实现
有了JFFS2文件系统及其对FLAsH的驱动耵D,下面就可以讨论JFFS2在UcLINUX系统中的具体实
现。下面是具体的实现步骤,这里用的n∞h是AM29LVl∞:
第一步:由于只0M设备和MTDBlock设备的主设备号(major)都是31,所以如果不想把JFFS2 作为根文件系统的话,必须修改他们之一的major。而修改JFFS2的设备major,在 u
CUnux-disnlinux-2.4.xVncIude、Iinux、m圳、mtd.h中把
#def.ne1 MTD—BLoCK.MAJOR 3改成
#d舒八e0 MTD-BLoCK-MAJOR 3第二步:添加MTD设备。在uCUnux-di龇怕ndo阽、sams帅g、4S10B、MaI(e啊le中添加MTD的
字符设备和块设备。
mtd0,c。∞.0 mtdl,c,∞,2、
mtdbl∞I(0。b。30,0 mldbI∞k1。b,30.1、 添加设备的数目根据你自己的需要酌情确定,另一点要说明的是:mtd字符设备次设备号(mlnor) 偶数是可擦写的,奇数是只读的。
第三步:添加在fl觞h上的map文件。在uCUnux.dis邓inux-2.4.蚋dnve噶\m埘\ma西下添加自 己mcu的map.这里添加的是s3c4510b.c,它是仿照同目录下的m5272c3.c修改的.具体程序见附 录,有几点说明:
(1)是关于FLASH。这里用的fIash是AM约LVl∞。它的容量是2M字节(或者1M字),程
序中的。
削枷neW斟DOWADOR0x0400∞∞
}埘e石neWINDl3^^,SlZEOIc:Ⅱ加∞O
#de啊neBUSWIDTH2 定义它的基地址,容量和宽度,它的基地址和容量可参看 uCUnux卅isn
的声明, BIinux.2.4.州ncIude、asm.anllnommu、arch?sndsloa、hardwa怕.h 中USWIDTH=2表示是16b_t.
删icstructms30451tcLpan街on0bLparti廿ons口巴{
{
name:”陀9erⅥBdforboaⅡoader(64K)”. size:0x010000。 01fset:0x0.
(2)程序中的
m∞Uags:MTD-WRrrEABLE
l,
{
name:。user(9∞IQ“。 size:0xF0【)00. o仟se
J;
七0)(10000
l
这是在月ash设备中分区情况,分了二个区,可以根据需要自己加减,masI(』ags:
MT叫^,R盯EABLE表示此区只读。