对ROMFS文件系统的分析和改进

发布者:MagicGarden最新更新时间:2012-03-26 来源: 微计算机信息 关键字:ROMFS  文件系统 手机看文章 扫描二维码
随时随地手机看文章

引言:ROMFS是在嵌入式设备上常用的一种文件系统,具备体积小,可靠性好,读取速度快等优点。同时支持目录,符号链接,硬链接,设备文件。但也有其局限性。ROMFS是一种只读文件系统,同时由于ROMFS本身设计上的原因,使得ROMFS支持的最大文件不超过256M。本文讨论了 ROMFS的原理,并针对其代码做了详细的分析,指出了ROMFS的优缺点并做了相应的改进。Linux, uclinux都支持ROMFS文件系统。除ROMFS外,其它常用的嵌入式设备的文件系统还有CRAMFS,JFFS2等,它们各有特色。

1.ROMFS文件系统的特点

ROMFS是一种只读的文件系统,它使用顺序存储方式,所有数据,包括目录,链接等都按目录树的顺序存放。相对于EXT2等较大型的文件系统而言,ROMFS非常节省空间。通常ROMFS用在嵌入式设备中作为根文件系统,或者用于保存boot loader以便引导系统启动。

2.ROMFS文件系统的数据存储方式

设计一个文件系统首先要确定它的数据存储方式。不同的数据存储方式对文件系统占用空间,读写效率,查找速度等主要性能有极大影响。ROMFS是一种只读的文件系统,它使用顺序存储方式,所有数据都是顺序存放的。因此ROMFS中的数据一旦确定就无法修改,这是ROMFS只能是一种只读文件系统的原因,它的数据存储方式决定了无法对ROMFS进行写操作。由于采用了顺序存放策略,ROMFS中每个文件的数据都能连续存放,读取过程中只需要一次寻址操作,进而就可以读入整块数据,因此ROMFS中读取数据效率很高。

整个ROMFS文件系统的布局如下:

ROMFS的首部


前八个字节是文件系统的名字,在这里是”-rom1fs-“, 8-11字节存放该文件系统大小,12-15字节为前512字节的校验和,从16字节开始是文件系统的卷名,卷名的长度必须的16字节的整数倍,不足的部分可以用‘0’填充。

ROMFS的首部是ROMFS的超级块信息,操作系统通过超级块来识别文件系统的类型。首部之后就是实际的数据,包括目录,普通文件,设备文件,硬链接等。ROMFS支持所有这些类型的文件。

ROMFS文件系统中文件存储方式:

   

   

[page]

3. ROMFS的主要数据结构

ROMFS的数据结构比较简单,主要有文件系统结构和文件结构两种数据结构。

ROMFS的文件系统结构如下:

struct romfs_super_block {

       __u32 word0;

       __u32 word1;

       __u32 size;

       __u32 checksum;

       char name[0];        /* volume name */

};

该结构用于识别整个ROMFS文件系统,大小为512字节,word0初始值为'-','r','o','m',word1初始值为 '-','1','f','s',通过这两个字操作系统确定这是一个ROMFS文件系统。size字段用于记录整个文件系统的大小,理论上ROMFS大小最多可以达到4G。checksum是前512字节的校验和,用于确认整个文件系统结构数据的正确性。前面4个字段占用了16字节,剩下的都可以用作文件系统的卷名,如果整个首部不足512字节便用0填充,以保证首部符合16字节对齐的规则。

ROMFS的文件结构如下:

struct romfs_inode {

       __u32 next;           /* low 4 bits see ROMFH_ */

       __u32 spec;

       __u32 size;

       __u32 checksum;

       char name[0];

};

next 字段是下一个文件的偏移地址,该地址的后4位是保留的,用于记录文件模式信息,其中前两位为文件类型,后两位则标识该文件是否为可执行文件。因此 ROMFS用于文件寻址的字段实际上只有28bit,所以ROMFS中文件大小不能超过256M。spec字段用于标识该文件类型。目前ROMFS支持的文件类型包括普通文件,目录文件,符号链接,块设备和字符设备文件。size是文件大小,checksum是校验和,校验内容包括文件名,填充字段。 name是文件名首地址,文件名长度必须保证16字节对齐,不足的部分用可以0填充。

4.ROMFS的实现

在Linux系统中定义一个文件系统首先要定义相应的file_system_type以及读取超级块的函数。具体到ROMFS本身,这两个对象分别是romfs_fs_type和romfs_read_super,通过宏DECLARE_FSTYPE_DEV来实现对romfs_fs_type的定义以及初始化工作。此外还需要实现对目录,文件的读写操作。

在Linux对ROMFS的实现中,比较重要的数据结构如下:

       //超级块操作表

static struct super_operations romfs_ops = {

       read_inode:     romfs_read_inode,

       statfs:             romfs_statfs,};

//页操作表

static struct address_space_operations romfs_aops = {

       readpage: romfs_readpage};

//常规文件操作表

static struct file_operations romfs_dir_operations = {

       read:              generic_read_dir,

       readdir:    romfs_readdir,};

//索引节点操作表

static struct inode_operations romfs_dir_inode_operations = {

       lookup:           romfs_lookup,};[page]

romfs_read_super()用来读取ROMFS文件系统的首部,并利用该首部初始化一个超级块对象作为相应ROMFS的超级块,具体流程如下

1 初始化超级块。

A 设置一次读取的块大小并初始化超级块对象某些域。

B 从指定ROMFS中读取第0块到一个缓冲区。bh=sb_bread(s, 0),其中s是文件系统的超级块对象。ROMFS的文件系统结构被保存到缓冲区bh中。

C 取出ROMFS的文件系统结构,rsb = (struct romfs_super_block *)bh->b_data,rsb是一个romfs_super_block结构,用以保存该ROMFS的文件系统结构的数据。然后对该数据进行检验,确定其文件系统类型,检验和,文件系统大小。

D 继续初始化超级块对象某些域,比较重要的是s_magic = ROMFS_MAGIC和s_flags |= MS_RDONLY,分别表明了该超级块的magic签名和s_flags参数,此处它们分别表示该文件系统类型为romfs,并且是只读文件系统。

2 给超级块对象的操作表赋值(s->s_op = &romfs_ops)

3 为根目录分配目录项 s->s_root = d_alloc_root(iget(s,sz), sz为文件系统开始偏移。

超级块操作表中romfs文件系统实现了两个函数

static struct super_operations romfs_ops = {

       read_inode:     romfs_read_inode,

       statfs:             romfs_statfs,};

函数romfs_read_inode是从ROMFS中读取一个inode索引节点对象并进行一些初始化工作,具体流程如下:

1 根据inode参数寻找对应的索引节点。

2 初始化索引节点某些域

3 根据该inode对应的文件的访问权限和类别来设置索引节点的相应操作表

  A 如果是目录文件则将索引节点操作表设为i_>i_op=&romfs_dir_inode_operations;文件操作表设置为i->i_fop=&romfs_dir_operations。

B 如果是常规文件,则将文件操作表设置为i->i_fop=&generic_ro_fops;将页高诉缓存表设置为i-> i_data.a_ops=&romfs_aops;由于romfs是只读文件系统,它在对常规文件操作时不需要索引节点操作,如 mknod,link等,因此不用设置索引节点操作表。

对常规文件的操作也只需要使用内核提供的通用函数表generic_ro_fops ,它包含基本的三种常规文件操作:

              llseek:             generic_file_llseek,

              read:                     generic_file_read,

              mmap:            generic_file_mmap,

这几种函数是块设备读取的通用函数,它们可以实现对ROMFS中常规文件的读取,寻址等操作。

C 如果是符号链接文件,则将索引节点操作表设置为
        i->i_op = &page_symlink_inode_operation;
page_symlink_inode_operations是通用的符号链接操作表。同时还需要实现页高速缓
存操作,因此将页高诉缓存表设置为i->i_data.a_ops=&romfs_aops。

D 如果是套接字或管道则进行特殊文件初始化操作init_special_inode(I,ino,nextfh);

函数romfs_statfs用于提取一些ROMFS的基本信息,包括文件系统大小,卷名等。相对而言非常简单。

5. 对ROMFS的改进

5.1 改进思路

ROMFS有紧凑,小巧等优点,但是也存在一些明显的不足。作为一个只读的文件系统,ROMFS的中文件最大只能达到256M。因此难以在 ROMFS中保存较大的文件。在实际工作中我们常常会碰到超过256M的大文件,因此本人对ROMFS做了一些改进,使它能够容纳超过256M的文件。

ROMFS中限制文件大小的原因在于ROMFS的文件结构。ROMFS采用连续存放数据的策略,每个文件都必须放在连续空间内,故文件寻址只能是一级寻址,不能通过增减数据块来改变文件大小。虽然ROMFS使用32位地址进行文件的寻址操作,但该32位地址的后4位留做它用,因此ROMFS实际用于文件寻址的地址只有28位,这就造成ROMFS的任意两个文件头之间地址相差不能超过256M,这就是ROMFS中文件大小不能超过256M的原因。[page]

针对这点我们可以做一些适当的改进工作,ROMFS的基本结构十分紧凑,能够改动的范围比较有限。为了尽可能保留原有代码的结构,我们没有在 ROMFS的文件结构中添加新字段,只是利用了文件名的填充字段作为对文件寻址的补充。在构造文件系统时在实际文件名后加上1个字节作为文件名的附加段,实际文件名加上附加段后写入文件系统作为该文件的文件名。附加段的前4位用来作为文件首地址的低4位。这样如果文件名不是16个字节整数倍则可以利用对文件名的填充字节,不会额外占用空间;如果文件名长度刚好为16字节的整数倍,那么加上一个字节的附加段后必须再填充15个字节以符合文件名保持16字节对齐的要求。这会浪费15个字节的空间,但文件名本身恰好满足16字节对齐的机会并不大,从概率角度讲只有1/16,因此是可以接受的。修改后ROMFS的文件结构如下:

在对文件寻址时,将next filehdr 字段的前28位和additional 字段的前4位合并起来作为下一个文件头起始地址,这样文件的寻址可以达到32位,ROMFS能够容纳的最大文件可以达到4G。

5.2 试验分析:

使用ROMFS生成一个文件系统。我们使用普通的Linux操作系统,内核版本为2.4.20-8,编译时选择支持ROMFS文件系统。至于romfs工具和源代码,可以从http://romfs.sourceforge.net得到。我们使用修改后的代码,同时对Linux中ROMFS的代码也要进行适当的修改,并重新编译内核。试验可以建立一个简单的目录FSROOT,目录结构如下:

FSROOT

FILE1

FILE2

SUBDIR1

FILE3

 

FILE1 和FILE2 大小为100M,FILE3大小为512M

生成romfs的命令如下(在当前目录下):genromfs  -f  romfs.bin  –d  FSROOT/

程序会根据目录FSROOT内容生成一个名为 romfs.bin的映像文件。选择一个挂载点,如/home目录,将生成的romfs.bin挂载到该目录下,命令为 mount –t romfs romfs.bin /home,将指定的映像文件挂载到/home目录下。可以用ls命令查看该目录。

[root@linuxserver home]# ls

[root@linuxserver home]# DIR1 FILE1 FILE2

[root@linuxserver home]# cd DIR1

[root@linuxserver DIR1]# ls

[root@linuxserver DIR1]# FILE3

可以看到新修改的ROMFS文件系统工作的很好,能够容纳超过256M的文件,达到了我们预期的目的。

6. 结束语

ROMFS是众多应用于嵌入式的文件系统之一,目前Linux和ucLinux都支持ROMFS。本文从数据的组织方式,基本数据结构,重要的操作的实现等方面详细分析了ROMFS的原理。同时指出了ROMFS一些局限性并做了一些改进工作。但是ROMFS本身的设计使其难以被修改为可擦写的文件系统,如果要在文件系统中提供可擦写功能,可以使用其它支持读写的嵌入式文件系统(比如JFFS2)以适应需要对闪存进行读写的应用。

本文的创新点在于对ROMFS 文件系统中文件寻址方法的改进,使得ROMFS可以支持更大的文件,满足了嵌入式设备中对存储系统更高的需求。

参考文献:

[1]   杨途军,郑明.嵌入式文件系统在触摸屏中的应用[J].微计算机信息.2005,5:100-101

[2]   孙建恒.嵌入式系统应用研究及实例[J].微计算机信息,2004,6:65-66

[3]   美 Moshe Bar《Linux文件系统》清华大学出版社

[4]   Jonathan Corbet,Alessandro Rubini Greg Kroah-Hartman《Linux设备驱动程序》 O’REILLY 中国电力出版社

[5]   Linux Kernel 2.4.20-8 Source Code[CP/OL].http://lxr.1inux. no/source/fs

[6]   Janos Farkas ,Jakub Jelinek  Genromfs 源代码. http://romfs.sourceforge.net

[7]   毛德操、胡希明,《linux内核源代码情景分析》浙江大学出版社

关键字:ROMFS  文件系统 引用地址:对ROMFS文件系统的分析和改进

上一篇:基于Framebuffer的嵌入式GUI系统实现
下一篇:嵌入式Linux实时技术改进与实现

推荐阅读最新更新时间:2024-05-02 21:58

构建根文件系统(2)Busybox init 进程
讲init进程的启动过程从/etc/inittab出发。 内核启动init进程时已经打开/dev/console设备作为控制台,一般情况下Busybox init程序就使用/dev/console, 如果内核启动init进程的同时设置了环境变量CONSOLE或console,则使用环境变量所指定的设备。 1、/etc/inittab文件的相关文档和示例代码都在Busybox 的examples/inittab文件中。 vi examples/inittab 内容如下(红色字为格式重要部分): # /etc/inittab init(8) configuration for BusyBox # # Copyright (C) 199
[单片机]
嵌入式设备上的文件系统优化设计
随着芯片技术的发展,各种处理器的处理能力不断提高,手持智能终端得到极大的普及。嵌入式Linux操作系统在未来的手持智能设备中将扮演着非常重要的角色,使嵌入式Linux的应用和研究不断的深入。 由于Microsoft公司的Windows操作系统占据了桌面操作系统绝大多数份额,而手持智能设备与PC机的数据交换又在所难免,因此,绝大多数的大容量嵌入式智能设备必须采用与PC机兼容的FAT/FAT32文件系统。随着便携式硬盘的应用,FAT32在嵌入式硬盘上已成为主流的格式。 同时,随着CPU处理能力的提高,面向存储的应用需求在手持智能设备上也随着不断增长,文件系统的访问性能将是未来的手持设备非常关键的因素。然而,当硬盘在手持智能设备
[嵌入式]
基于FAT16文件系统的嵌入式温度记录器
  闪存技术的不断发展,使得闪存卡(如SD卡、MMC卡等)因其体积小、容量大、可靠性高等优点而在嵌入式存储领域得到越来越广泛的应用。 FAT16文件系统具有出色的文件管理性能,能被大多数操作系统识别,因此将闪存卡与FAT16文件系统相结合是嵌入式存储、记录系统中一个理想的方案。温度采集与控制技术是现代测量、控制系统的一个重要组成部分。由于传统的模拟传感测量温度系统存在测量精度低、易受干扰、硬件复杂、调试繁琐等不利因素,而新型单片数字式温度传感器具有测量精度高、抗干扰能力强、操作方便、功耗低等优点,应用范围越来越广泛。本嵌入式数字温度记录器以ARM7微处理器 LPC2148、数字温度传感器ADT75为基础,采用大容量SD卡作为存储介
[单片机]
基于FAT16<font color='red'>文件系统</font>的嵌入式温度记录器
构建根文件系统(5)构建dev目录
只讲使用mdev创建设备文件。。。。。 1、mdev的用法可以参考busybox-1.9.2/docs/mdev.txt,它的两个用途:初始化/dev目录、动态更新。 以下为摘取部分关于mdev的命令: Here's a typical code snippet from the init script: mount -t sysfs sysfs /sys echo /bin/mdev /proc/sys/kernel/hotplug mdev -s Of course, a more full setup would entail executing this before the previous
[单片机]
uClinux下Nor Flash的JFFS2文件系统构建
摘要:目前的嵌入式系统多使用FLASH作为主存,因此,如何有效管理FLASH上的数据非常重要。文章以SST39VF160芯片为例,讨论了在Nor Flash上建立uClinux的JFFS2文件系统的一般步骤,从而为FLASH上的数据管理提供了理想的选择方式。 关键词:uClinux;Nor Flash;MTD;JFFS2;文件系统 嵌入式系统正随着Internet的发展而在各个领域得到广泛的应用,作为嵌入式应用的核心,嵌入式Linux以其自由软件特性正日益被人们看好。Linux具有内核小、效率高、源代码开放等优点,还内涵了完整的TCP/IP网络协议,因此非常适于嵌入式系统的应用。而作为专门运行于没有MMU的微处理器的嵌入式操作
[应用]
文件系统的移植(二):nfs 文件系统
内 核 版 本:linux-3.0 u-boot版本:u-boot-2010.09 开发板型号:FL2440 我们在上面移植了 initramfs 文件系统,并且已经成功运行了。下面我们开始移植nfs,之前开启PC 上的nfs 服务功能 确认并安装 NFS 服务依赖软件包。 在使用 NFS 共享文件之前,我们首先使用rpm 命令确认我们安装了这些应用程序。如果没有安装,则从安装光盘中找到他们并安装,或者使用 yum 安装。下面显示我们在安装系统时,已经选择安装了NFS 服务相关软件。 1、修改主机上的 NFS 配置文件,导出/home/lingyun/keyue目录使用NFS 共享: $ sudo vi
[单片机]
<font color='red'>文件系统</font>的移植(二):nfs <font color='red'>文件系统</font>
SmartARM3250用户文件系统烧写办法
烧写内核和安全文件系统后,在U-Boot下,输入run safemode可进入安全系统,在安全系统下,烧写用户文件系统。 烧写用户文件系统实际上就是将文件系统压缩包rootfs.tar或者rootfs.tar.bz2释放到NAND FLASH分区。 大致流程如下: (1)将NAND FLASH用户文件系统分区MTD4 mount到系统某个目录下,如/mnt目录: (2)将存放rootfs.tar或者rootfs.tar.bz2文件系统档案包的介质(如U盘、SD卡、CF卡或者NFS服务器)挂在到系统另外一个目录,如/tmp目录。 (3)将/tmp目录下的rootfs档案包释放到MTD挂在目录/mnt,等待释放完毕, (4)卸
[单片机]
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved