废矿物油应急措施:ROMFS文件系统分析

来源:百度文库 编辑:中财网 时间:2024/04/30 06:41:35

ROMFS文件系统分析

作者:许振文
ROMFS是一种简单的只读文件系统,主要是用来当做初始文件系统来使用的,在嵌入式linux或是uclinux中通常使用这中文件系统来作为引导系统的文件系统,甚至uclinux有时就直接把ROMFS作为其根文件系统,而不是将其作为系统启动中的过渡文件系统。在前面我也分析过,linux操作系统启动中一个是要加载内核,另一个就是要加载一个用于系统简单初始化的文件系统。这个文件系统的格式也是经过了很多发展的。现在一般使用的是一中cpio的格式。在嵌入式系统中一般使用romfs+其它的可读文件系统。romfs由于它的小巧性(其内核编译只有4000字节),所以非常适合作为系统启动初始化的文件系统。本文就是对ROMFS文件系统进行结构上的分析。前面我也曾对其源代码结构进行了简单的分析。关于ROMFS最为权威的资料是内核源代码树下的“Documentation/filesystems/romfs.txt”。本文多数资料就是来自于该文件。

ROMFS文件系统的制作

一般我们可以使用一些工具来制作ROMFS的文件系统。制作好之后其实也就是一个二进制的文件。制作工具一般使用”genromfs“,这个工具在网上就可下载到,其源代码并不是很多,只有不到900行。
以下是genromfs工具所支持的参数:
xux@zhwen:~/fs-sys$ genromfs -hgenromfs 0.5.2Usage: genromfs [OPTIONS] -f IMAGECreate a romfs filesystem image from a directory  -f IMAGE               Output the image into this file  -d DIRECTORY           Use this directory as source  -v                     (Too) verbose operation  -V VOLUME              Use the specified volume name  -a ALIGN               Align regular file data to ALIGN bytes  -A ALIGN,PATTERN       Align all objects matching pattern to at least ALIGN bytes  -x PATTERN             Exclude all objects matching pattern  -h                     Show this helpReport bugs to chexum@shadow.banki.huxux@zhwen:~/fs-sys$ 
参数解释:
-f IMAGE     指定输出romfs映像的名字
-d DIRECTORY 指定源目录(将该目录制作成romfs文件系统)
-v           显示详细的创建过程
-V VOLUME    指定卷标
-a ALIGN     指定普通文件的对齐边界(默认为16字节)
-A ALIGN,PATTERN 匹配参数PATTERN的对象对齐在ALIGN边界上
-x PATTERN 不包括匹配PATTERN的对象。
-h 显示帮助文档。
以下是如何制作生成一个romfs的文件系统:
xux@zhwen:~/fs-sys$ lstest  xux@zhwen:~/fs-sys$ ls test/test  xux  zhwenxux@zhwen:~/fs-sys$ genromfs -V "xromfs" -f romfs.img -d testxux@zhwen:~/fs-sys$ lsromfs.img  test xux@zhwen:~/fs-sys$ file romfs.img romfs.img: romfs filesystem, version 1 592 bytes, named xromfs.xux@zhwen:~/fs-sys$ sudo mount romfs.img /mnt -o loopxux@zhwen:~/fs-sys$ ls /mnt/test  xux  zhwenxux@zhwen:~/fs-sys$ 

ROMFS文件系统结构分析

ROMFS系统中最大文件的大小理论上可以达到4G,文件名的大小一般小于16字节,而且整个文件系统都是以16字节来对齐。
其结构如下:
offset      content        +---+---+---+---+  0     |  -  |  r  |  o  | m  |          +---+---+---+---+    The ASCII representation of those bytes  4     |  1  |  f  |  s  |  -  |  /    (i.e. "-rom1fs-")        +---+---+---+---+  8     |     full size       |    The number of accessible bytes in this fs.        +---+---+---+---+ 12     |    checksum   |       The checksum of the FIRST 512 BYTES.        +---+---+---+---+ 16     |  volume name     |    The zero terminated name of the volume,        :               :       padded to 16 byte boundary.        +---+---+---+---+ xx     |     file      |        :    headers    :

File headers之前的字节由如下的数据结构来控制:include/linux/romfs_fs.h

/* On-disk "super block" */struct romfs_super_block {        __be32 word0;        __be32 word1;        __be32 size;        __be32 checksum;        char name[0];           /* volume name */};
(1)这个数据结构中的word0和word1的是固定的值:“-rom1fs-”,由如下的宏定义说明:
include/linux/romfs_fs.h
#define ROMSB_WORD0 __mk4('-','r','o','m')#define ROMSB_WORD1 __mk4('1','f','s','-')
(2)而size是对整个文件系统的大小的说明。
(3)checksum是对前512个字节的校验和(如果小于512,就以实际大小计算)。
(4)name是当前这个文件系统的名称。

下面在来看文件的堆放格式

offset      content        +---+---+---+---+        |     file header    |              +---+---+---+---+              |      file date     |              +---+---+---+---+              |     file header    |              +---+---+---+---+              |      file date     |              |     file header    |              +---+---+---+---+              |      file date     |              +---+---+---+---+              |      …….        |              +---+---+---+---+      

File header的格式如下

offset      content        +---+---+---+---+  0     | next filehdr   | X  |       The offset of the next file header        +---+---+---+---+         (zero if no more files)  4     |   spec.info       |       Info for directories/hard links/devices        +---+---+---+---+  8     |        size       |       The size of this file in bytes        +---+---+---+---+ 12     |    checksum     |       Covering the meta data, including the file        +---+---+---+---+         name, and padding 16     |    file name      |       The zero terminated name of the file,        :                    :       padded to 16 byte boundary
在内核源代码中如下:include/linux/romfs_fs.h
/* On disk inode */struct romfs_inode {        __be32 next;            /* low 4 bits see ROMFH_ */        __be32 spec;        __be32 size;        __be32 checksum;        char name[0];};
(1)其中next的前面28位是指向下一个文件的地址,应为整个文件系统以16字节对齐,所以任何一个文件的起始地址的最后4位始终为“0”。
而这最后的4位并没就此浪费,而是进行了新的利用--指定文件的类型和是否可执行。在linux下文件的类型分为:目录,一般文件,链接文件,管道文件,设备文件等。所以这4位中的最高一位使用来表示该文件是否可执行,而其余三位使用来表示该文件的类型。
include/linux/romfs_fs.h
#define ROMFH_TYPE 7#define ROMFH_HRD 0#define ROMFH_DIR 1#define ROMFH_REG 2#define ROMFH_SYM 3#define ROMFH_BLK 4#define ROMFH_CHR 5#define ROMFH_SCK 6#define ROMFH_FIF 7#define ROMFH_EXEC 8
(2)spec这个字段存放的是目录/硬链接/设备文件的相关信息:
这个域是文件类型相关的,也就是说对于不同的文件类型,这个域表示的含义是不一样的。下面是具体的说明;来自“Documentation/filesystems/romfs.txt”。
          mapping               spec.info means 0      hard link       link destination [file header] 1      directory       first file's header 2      regular file    unused, must be zero [MBZ] 3      symbolic link   unused, MBZ (file data is the link content) 4      block device    16/16 bits major/minor number 5      char device                 - " - 6      socket          unused, MBZ 7      fifo            unused, MBZ
(3)size是这个文件的大小。
(4)checksum这个域只是文件头和文件名的校验和。
(5)name是文件的名称。