嵌入式Linux文件系统
[TOC]
不同存储介质上常用文件系统类型
在嵌入式系统中,常见的存储介质为NorFlash、NandFlash、eMMC和SD卡,这些存储介质我们统称为Flash存储器。Flash存储器根据自身是否带有控制器又分为两种:
Flash芯片设备(Raw Flash device,也叫MTD设备,不带控制器 既不是字符设备,也不是块设备)
NOR Flash:JFFS2(常用)、Squashfs(只读)、Cramfs(只读,已经过时,很少用)
NAND Flash:YAFFS2(常用)、Squashfs(只读)、UBIFS(常用)
带Flash控制器的设备(Flash Translation Layer device, FTL设备 带控制器 作为块设备处理)
SD:Ext4(常用)
eMMC:Ext4(常用)
SSD:(嵌入式设备很少用作文件系统,这里不讲)
USB:(嵌入式设备很少用作文件系统,这里不讲)
HDD:(嵌入式设备很少用作文件系统,这里不讲)
两者的关键区别是是否带有Flash控制器,这也直接决定了文件系统分为不同的两类。
除了上面提到的文件系统类型,还有写基于ram的文件系统ramfs、tmpfs、ramdisk和网络的文件系统nfs,总体框架如下:

基于Flash文件系统
JFFS2
介绍
JFFS意为Journaling Flash File System,该文件系统是瑞典Axis通信公司开发的一种基于Flash存储器的日志文件系统。该公司于1999年在GNU/Linux上发行了第一版JFFS文件系统,后来经过Redhat公司的发展,发行了第二个版本的JFFS2。
优点 使用了压缩的文件格式。最重要的特性是可读写操作。
缺点:
JFFS2 文件系统挂载时需要扫描整个 JFFS2 文件系统,因此当 JFFS2 文件系统分区增大时,挂载时间也会相应的变长。使用 JFFS2 格式可能带来少量的 Flash 空间的浪费。这主要是由于日志文件的过度开销和用于回收系统的无用存储单元,浪费的空间大小大致是若干个数据段。 JFFS2 的另一缺点是当文件系统已满或接近满时, JFFS2 运行速度会迅速降低。这是因为垃圾收集的问题。
注意:
日志结构文件系统并不采用本地更新的方式,而是采用异步更新的方式,即当某个数据块需要更新时,先找一个新块将新数据写入,再将旧块擦除。不过旧数据并不马上在闪存中擦除,而是以日志方式作为历史记录保存下来,这为文件系统的恢复操作打下了基础
不适合用于NAND闪存的主要是因为NAND闪存的容量一般较大,这样导致jffs为维护日志节点所占用的内存空间迅速增大,另外jffs文件系统在挂载时需要扫描整个FLASH的内容,以找出所有的日志节点,建立文件结构,对于大容量的NAND闪存会耗费大量时间。
制作jffs2文件系统
手动命令生成
手动生成
# 下载jffs2文件系统制作工具
sudo apt-get install mtd-utils
# 进入自己的文件系统路径,这里以bulidroot生成的文件系统路径为例【output/images】
cd output
ls output/images
bin dev etc lib lib32 linuxrc media mnt opt proc root run sbin sys tmp usr var
# 使用mkfs.jffs2工具生成 rootfs.jffs2
# -d :指定要做成image的目录名
# -o : 指定输出image的文件名
# -s :页大小 0x100 256 字节
# -e :块大小 0x10000 64k
# -p :或--pad 参数指定 jffs2 分区总空间
# -n :如果挂载后会出现类似:CLEANMARKER node found at0x0042c000 has totlen 0xc != normal 0x0 的警告,则加上-n 就会消失。
# -m :压缩方式 none
# 为根文件系统制作jffs2镜像包
sudo mkfs.jffs2 -s 0x100 -e 0x10000 -m none -p 0x3200000 -d images/ -o rootfs.jffs2
# 或者
sudo mkfs.jffs2 -s 0x100 -e 0x10000 -m none --pad=0x3200000 -d images/ -o rootfs.jffs2

Buildroot自动生成
在Buildroot根目录执行
make menuconfig,进入【Filesystem images】选项
【Filesystem images】选项下配置如下:

配置好好后执行
make命令make的时候可能会报下面的错误,这是由于执行mkfs.jffs2 工具权限问题

只需进行下面的修改:在buildroot根目录下【fs/jffs2/jffs2.mk】文件新增
sudo即可,如下:
最终生成镜像文件rootfs.jffs2路径如下:

配置系统支持jffs2文件系统
todo
验证
todo
YAFFS2
介绍
yaffs/yaffs2 是专门为 NAND Flash 设计的嵌入式文件系统。它是日志结构的文件系统,提供了损耗平衡和掉电保护,可以有效地避免意外掉电对文件系统一致性和完整性的影响。与jffs2相比,它减少了一些功能(例如不支持数据压缩),所以速度更快,挂载时间很短,对内存的占用较小。它是跨平台的文件系统,除了Linux和eCos,还支持WinCE, pSOS和ThreadX等。 yaffs/yaffs2 的优缺点如下:
优点: 专门针对 NAND Flash,软件结构得到优化,速度快。 使用硬件的 spare area 区域存储文件组织信息,启动时只需扫描组织信息,启动比较快。 采用多策略垃圾回收算法,能够提高垃圾回收的效率和公平性,达到损耗平衡的目的。
缺点: 没有采用压缩的文件格式。当包含的内容相同时, yaffs2 镜像文件要比 jffs2 镜像文件大。
注意: yaffs与yaffs2的主要区别在于,前者仅支持小页(512 Bytes)NAND闪存,后者则可支持大页(2KB) NAND闪存。同时,yaffs2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升。与jffs2相比,它减少了一些功能(例如不支持数据压缩),所以速度更快,挂载时间很短,对内存的占用较小。
制作yaffs文件系统
手动命令生成
手动制作yaffs2文件系统 需要自行下载mkyaffs2image工具(下面默认系统已经安装mkyaffs2image)
我自己的mkyaffs2image安装目录如下:

# 进入自己的文件系统路径,这里以bulidroot生成的文件系统路径为例【output/images】
cd output
ls output/images
bin dev etc lib lib32 linuxrc media mnt opt proc root run sbin sys tmp usr var
# 第一个参数指定要打包目录
# 第二个参数指定输出文件名
# 第三个参数指定打包方式
mkyaffs2image images/ rootfs.yaffs2 2048
最终生成的rootfs.yaffs2如下所示:


Buildroot自动生成
在Buildroot根目录执行
make menuconfig,进入【Filesystem images】选项
【Filesystem images】选项下配置如下:

配置好好后执行
make命令make的时候可能会报下面的错误,这是由于权限问题


解决方法去下:


最终生成镜像文件rootfs.yaffs2路径如下

配置系统支持yaffs2文件系统
todo
验证
Sqsh4fs
介绍
squashfs 是一个高度压缩的只读文件系统,它可以将高达 2-3GB 的数据压缩到一个只有 700M 的文件,squashfs 系统支持以回环(loopback)的方式挂载,然后便可以访问其上的文件了,在访问这些文件时,它们就会被解压缩并装载在 RAM 中,而不需要将整个文件解压缩后才去访问其中的文件,这样一来访问速度就快多了
制作sqsh4fs文件系统
手动命令生成
手动生成
# 进入自己的文件系统路径,这里以bulidroot生成的文件系统路径为例【output/images】 cd output ls output/images bin dev etc lib lib32 linuxrc media mnt opt proc root run sbin sys tmp usr var # images/ 需要打包的文件系统 # rootfs.sqsh4 生成的文件系统名字 # -noappend do not append to existing filesystem # -comp xz 压缩方式 # -b 64K block_size Default 128 Kbytes mksquashfs images/ rootfs.sqsh4 -noappend -comp xz -b 64K
执行后最终结果如下:

注意如果在打包的时候想排除某些文件可以用-e参数,如果排除的文件过多,可以把文件写入一个文件中exclud_list,用-f参数指定该文件
mksquashfs images/ rootfs.sqsh4 -noappend -comp xz -b 64K -e images/hello.c
mksquashfs images/ rootfs.sqsh4 -noappend -comp xz -b 64K -ef exclud_list
Buildroot 自动生成
进入【Filesystem images】勾选

编译
make编译的时候可能会报下面的权限错误

解决方式如下:

最终生成的结果如下:

配置系统支持sqsh4fs文件系统
todo
验证
todo
UBIFS
介绍
UBIFS(Unsorted Block Image File System)最早在2006年由IBM与Nokia的工程师Thomas Gleixner,Artem Bityutskiy所设计,专门为了解决MTD(Memory Technology Device)设备所遇到的瓶颈。由于NAND Flash容量的暴涨,YAFFS等皆无法再去控制NAND Flash的空间。UBIFS通过UBI子系统处理与MTD device之间的动作。与JFFS2一样,UBIFS 建构于MTD device 之上,因而与一般的block device不兼容。
UBIFS在设计与性能上均较YAFFS2、JFFS2更适合NAND Flash,例如:UBIFS 支持 write-back, 其写入的数据会被cache, 直到有必要写入时才写到Flash,大地降低分散小区块数量并提高I/O效率。UBIFS文件系统目录存储在Flash上,UBIFS mount时不需要scan整个Flash的数据来重新创建文件目录。
整体框架如下图所示:

uboot分区参数和ubifs对应关系
setenv mtdids "nand0=nand0"
setenv bootargs "console=ttyS0,115200n8 ubi.mtd=6 root=ubi0:ROOTFS rootfstype=ubifs rw "
setenv mtdparts "mtdparts=nand0:256K(UBOOT),64K(ENV),64K(ENVBK),64K(DTB),2560K(KERNEL),512K(LOGO),4096K(ROOTFS),-(WORK)"
# 还有另外一种写法 其中@ 后面为偏移地址
setenv mtdparts "mtdparts=nand0:256K@0x0(UBOOT),64K@0x40000(ENV),64K@0x50000(ENVBK),64K@0x60000(DTB),2560K@0x70000(KERNEL),512K@0x2f0000(LOGO),4096K@0x370000(ROOTFS),-@0x770000(WORK)"
#注意:从mtdparts参数可以看出,一共有8个mtd分区分别为mtd0~mtd7 其中ROOTFS对应的就是mtd6
整个分区下来结构如下图所示:

说明:
ubi.mtd=6
ubiattach mtd6 到到ubi设备上(设备名为ubi0), mtd6就是上面图中的mtdblock6,对应的就是文件系统ROOTFS分区。
root=ubi0:ROOTFS有两种写法
root=ubi0:ROOTFSubi0 是ubi device 名 ROOTFS是 ubi volume名
root=ubi0_0ubi0 是ubi device 名 _0 是 ubi volume 编号
制作ubifs文件系统
手动生成
sudo mkfs.ubifs -x lzo -m 2048 -e 129024 -c 300 -r ./rootfs -o rootfs.ubifs
# 参数说明:
# -x lzo 指定使用lzo压缩方法,默认是lzo,还支持zlib,zlib压缩率高些,但是lzo压缩解压速度快 。
# -m 2048 Nand Flash的最小读写单元,一般为page size,K9F2G08的页大小为2048字节。
# -r 指定要打包根文件系统目录树的路径为 ./rootfs
# -o 指定输出根文件系统镜像文件名为 rootfs.ubifs 注意:名字可以随便取
# -e 129024 指定LEB(Logical Erase Block,逻辑擦除块)大小。
# Nandflash读写单位为页,擦除单位为块,
# K9F2G08Nandflash一个块是64个页(page_nums),而一个页大小为2048字节(page_size)。
# 一个块大小 block_size = 2048*64=131072
# 逻辑擦除块-e参数取值的算法 = [block_size-1*page_size]=131072-1*2048=129024
# -c 300 指定该分区最大逻辑擦除块数量,该值随着根文件系统分区的大小和该分区的坏块数调整。
# 该值很重要,不能大也不能小,最小也要大于image大小,太大mount有问题。
# 比如40MiB的mtd分区,一共有40*1024*1024/2048/64 = 320个块
# 减去2个volume table的块
# 减去1个wear-leveling块
# 减去1个atomic LEB change块
# 减去以及一些坏块处理的保留块(坏块容忍数比如16)。因为一个分区上有多少个坏块是随机的,不要担心这个会浪费空间,下面的ubinize的autoresize选项就是解决这个问题的。
#
# 在这里我们最终的逻辑擦除块个数计算公式为:
# 320-2(volume table)-1(Wear-leveling)-1(atomic LEB change)-16(坏块容量数)=300
UBIFS是建立在UBI之上的文件系统,因此使用mkfs.ubifs制作的根文件系统镜像不能直接使用u-boot的nand write命令烧录,这时我们可以使用ubinize命令对rootfs.ubifs文件进行处理后,就可以在u-boot上直接用nand write命令写入到根文件系统分区了。该命令的使用步骤如下:
创建配置
ubinize.cfg,且内如如下:[ubifs-volume] mode=ubi image=./rootfs.ubifs vol_id=0 vol_size=38707200 vol_type=dynamic vol_name=ROOTFS vol_flags=autoresize vol_alignment=1
配置文件说明如下:
mode=ubi image=./rootfs.ubifs # 指定rootfs.ubifs制作生成的根文件系统镜像源; vol_id=0 # ubi volume 编号0,u-boot的bootargs参数root=ubi0_0中后面那个_0 vol_size=38707200 # 指定该UBI逻辑卷的大小,该值计算公式一般为 逻辑擦除块大小*逻辑擦除块个数=129024*300=38707200 该值一般不用写,默认值是image大小。写了这个作用是帮助检查image是否超过了分区限制,制作时候就提示,否则mount会出错。逻辑擦除块个数的值是经过计算的最大值(前面mkfs.ubifs -c指定的300)了,不过autoresize参数会自适应大小,不会浪费空间的 vol_type=dynamic vol_name=ROOTFS # 指定UBI卷的名称,u-boot的bootargs参数root=ubi0:ROOTFS vol_flags=autoresize # UBI Subsystem在系统启动时自动调整逻辑擦除块的个数 vol_alignment=1
执行
ubinize命令# -o 最后生成的可用于uboot阶段使用nand命令烧录到flash的bin文件名,这里命名为:rootfs_ubifs.bin # -m 最小输入输出大小为2KiB(2048bytes),一般为页大小 # -p 块大小 131072=64*2048 # -s 512 指定sub-page-size大小,页大小为2048字节的nandflash对应值为512;对于其他的Nandflash可以在Linux内核跑起来后挂载ubifs后查看该值 # -O 512 指定vid-hdr-offset值,默认为sub-page-size的值,可以省略不用 ubinize -o rootfs_ubifs.bin -m 2048 -p 131072 -s 512 -O 512 ubinize.cfg
uboot阶段使用nand命令 烧录
rootfs_ubifs.bin到nandflash中# tftp 网络命令烧录服务器上的rootfs_ubifs.bin 到DDR的30008000处 tftp 30008000 rootfs_ubifs.bin # 擦除nandflash的1000000处的2800000字节 这部分用来存放文件系统 用户要根据自己的硬件自己分区 nand erase 1000000 2800000; # 把DDR中30008000处的rootfs_ubifs.bin写入到nandflash的1000000地址处,写入字节数为filesize 即rootfs_ubifs.bin的大小(单位字节) nand write 30008000 1000000 $filesize
设置
bootargs,修改关于ubifs的地方参见前面介绍的【uboot分区参数和ubifs对应关系】章节
Buildroot 自动生成
todo
配置系统支持ubifs文件系统
todo
验证
todo
ubi之上运行squashfs文件系统
由于ubifs是运行在UBI卷之上的文件系统,而squashfs是运行在block device之上的文件系统,二者本来无任何交集,但是UBI提供了能够在ubi卷之上创建只读块设备的特性(R/O block devices on top of UBI volumes),这使得squashfs也能够“运行”在ubi卷之上。其实,在ubi之上运行squashfs文件是openwrt系统中常见的方式。框架如下图红色所示,关键就在于在ubi1:0卷上使用ubiblock命令 创建了只读块设备ubiblock1_0,所以才可以使用mount命令挂载ubiblock1_0为squashfs文件系统。

演示
下面将以实例演示如何实现在ubi之上运行squashfs:
在进行如下操作之前,需要了解nand flash一些参数。这是我正在使用的nand flash的参数:
block size 256KB # 块大小 一个块是64个页
page size 4KB # 页大小
(UBI)LEB 248KB # 逻辑擦除块 [block_size-1*page_size]=256-1*4=252k 这里还可以在少点 暂定248
(UBI)PEB 256KB # 物理擦除块 一般为一个块大小
flash total size 4096 blocks # 总共块数量
flash min I/O size 4KB
制作squashfs
制作squashfs需要用到mksquashfs工具
创建fs目录内容如下:
$ ls
apps this_is_squashfs.txt
执行如下命令:根据fs目录创建squashfs,输出的squashfs镜像文件为 squashfs.img
mksquashfs fs/ squashfs.img -b 256k -nopad -noappend -root-owned -comp xz -processors 1
# -b 指定 flash一个block的大小
# -comp xz 指定压缩算法为 xz
# -root-owned 文件系统内所有文件的owner都是root
# -noappend 不追加到已存在的文件系统
# -nopad 不要将文件系统填充到 4K 的倍数
# -processors 1 使用 1个处理器构建文件系统
制作ubifs
制作squashfs需要用到mkfs.ubifs工具
创建fs目录内容如下:
$ ls
apps this_is_ubifs.txt
执行如下命令:根据fs目录创建ubifs,输出的ubifs镜像文件为 ubifs.img
mkfs.ubifs -m 4KiB -e 248KiB -c 128 --space-fixup --compr=lzo --squash-uids -r fs -o ubifs.img
制作ubi镜像
制作ubi镜像需要用到ubinize工具
[my_squashfs]
mode=ubi
vol_id=0
vol_type=dynamic
vol_name=my_squashfs
image=squashfs.img
[my_ubifs]
mode=ubi
vol_id=1
vol_type=dynamic
vol_name=my_ubifs
vol_flags=autoresize
image=ubifs.img
上述配置文件包含2个卷:
动态卷0,为其分配ID 0 并命名为
my_squashfs,卷的内容取自squashfs.imgmy_squashfs 卷的类型必须是dynamic,否则后续无法挂载
动态卷1,为其分配 ID 1 并命名为
my_ubifs, 卷的内容取自ubifs.img
最后,执行如下命令生成ubi镜像ubi.image
ubinize -m 4KiB -p 256KiB ubinize.cfg -o ubi.image
烧写ubi镜像
上一步骤生成的ubi.image可以直接写入flash,这里使用ubiformat工具进行烧写。
烧写ubi镜像
ubiformat /dev/mtd3 -y -f ubi.image
ubiattach
ubiattach -p /dev/mtd3
ubiattach之后会生成新的ubi设备以及ubi卷。 我这里就生成了ubi2,并且根据ubinize.cfg配置文件自动生成了两个卷:my_squashfs和myubifs$ ubinfo -a /dev/ubi2 Volume ID: 0 (on ubi2) Type: dynamic Alignment: 1 Size: 1 LEBs (253952 bytes, 248.0 KiB) State: OK Name: my_squashfs Character device major/minor: 506:1 ----------------------------------- Volume ID: 1 (on ubi2) Type: dynamic Alignment: 1 Size: 111 LEBs (28188672 bytes, 26.8 MiB) State: OK Name: my_ubifs Character device major/minor: 506:2
挂载
对于ubifs可以直接挂载,使用/dev/ubi2_1挂载即可:
mount -t ubifs /dev/ubi2_1 /test
查看文件系统中的文件如下:
ls /test -l
drwxrwxr-x 2 root root 224 Jun 22 14:00 app
-rw-rw-r-- 1 root root 16 Jun 22 14:00 this_is_ubifs.txt
对于squashfs还需要进一步操作:
创建只读块设备
ubiblock工具用于创建或者销毁ubi块设备,使用方法如下:Usage: ubiblock [-c,-r] <UBI volume node file name> Example: ubiblock -c /dev/ubi0_0 ubiblock -r /dev/ubi0_0
基于
ubi2_0创建ubi块设备的命令如下:# ls /dev/ubiblock2* -l brw------- 1 root root 252, 1 Jun 22 14:38 /dev/ubiblock2_0
使用上述块设备就可以挂载
squashfs了mount -t squashfs /dev/ubiblock2_0 /test1
查看文件系统中的文件如下:
# ls test1/ -l drwxrwxr-x 2 root root 30 Jun 22 10:51 apps -rw-rw-r-- 1 root root 47 Jun 22 13:59 this_is_squashfs.txt
查看挂载信息:
$ mount /dev/ubi2_1 on /test type ubifs (rw,relatime,assert=read-only,ubi=2,vol=1) /dev/ubiblock2_0 on /test1 type squashfs (ro,relatime)
UBI相关的工具
ubi的工具集成在包mtd-utils中,分别有以下工具及其作用
| 工具 | 作用 |
|---|---|
| ubinfo | 提供ubi设备和卷的信息 |
| ubiattach | 链接MTD设备到UBI并且创建相应的UBI设备 |
| ubidetach | ubiattach相反的操作,将MTD设备从UBI设备上去链接 |
| ubimkvol | 从UBI设备上创建UBI卷 |
| ubirmvol | 从UBI设备上删除UBI卷 |
| ubiblock | 管理UBI卷上的block |
| ubiupdatevol | 更新卷,例如OTA直接更新某个分区镜像 |
| ubicrc32 | 使用与ubi相同的基数计算文件的crc32 |
| ubinize | 制作UBI镜像 |
| ubiformat | 格式化空的Flash设备,擦除Flash,保存擦除计数,写入UBI镜像到Flash |
| mtdinfo | 报告从系统中找到的UBI设备的信息 |
| cat /proc/mtd | 查看系统分区 |
uboot中的ubi 命令
mtdparts:查看MTD分区表mtdparts default:载入默认分区表,用的比较少ubi part ROOTFS:激活分区 其中ROOTFS为mtdparts里面指定的文件系统的名字ubi part:查看当前激活的分区ubifsmount ROOTFS:挂载分区ubifsls:查看分区内容ubifsload 80008000 /root/readme:md 80008000查看某个文件,其中
80008000DDR地址,/root/readme为要查看的文件名ubi create<volume> <size>: 建立一个volumeubi write <addr> <volume> <大小>:从addr中 写入size 大小的 ubi 文件系统到 volumeubi read <addr> <volume> <大小>: 从volume中读入size大小的ubi文件系统到addrubi remove <volume>: 移除 volume
Ext4
介绍
todo
制作ext4文件系统
手动命令生成
# 查看mkfs.ex4 版本
# 1.dd命令生成空的文件 一次操作块大小512k 一共1024个块, 一共512M 该量和自己文件系统大小相关
dd if=/dev/zero of=rootfs.ext4 bs=512k count=1024 && sync
# 2.使用mkfs.ext4命令格式化rootfs.ext4为ext4类型 需要主语mkfs.ext4 版本
mkfs.ext4 -O ^metadata_csum rootfs.ext4 #高于1.43 需要使用 -O ^metadata_csum 属性
mkfs.ext4 rootfs.ext4 #低于1.43 不需要 -O ^metadata_csum 属性
# 3.使用ext4格式 挂载rootfs.ext4 到系统的/mnt目录下
sudo mount -t ext4 rootfs.ext4 /mnt
# 4.解压自己的制作好的文件系统 到挂载点/mnt
sudo tar -xjf rootfs.tar.bz2 -C /mnt
#5.卸载挂载点
sudo umount /mnt
uboot 有 ext2 和 ext4 这两种格式的文件系统的操作命令,常用的就四个命令,分别为:ext2load、 ext2ls、 ext4load、 ext4ls 和 ext4write。这些命令的含义和使用与 fatload、 fatls 和 fatwrit一样,只是 ext2 和 ext4 都是针对 ext 文件系统的 ,具体如下:
| 命令 | 描述 |
|---|---|
| ext2ls | 用于查询 ext2 格式设备的目录和文件信息 |
| ext4ls | 用于查询 ext4 格式设备的目录和文件信息 |
| ext2load | 用于将指定的文件读取到 DRAM 中 |
| ext4load | 用于将指定的文件读取到 DRAM 中 |
| ext4write | 用于将 DRAM 中的数据写入到 MMC 设备中 |
| ext2write | 用于将 DRAM 中的数据写入到 MMC 设备中 |
比如 ext4ls 命令, EMMC 的分区 2 就是 ext4格式的,使用 ext4ls 就可以查询 EMMC 的分区 2 中的文件和目录,输入命令

Buildroot自动生成
todo
配置系统支持ext4文件系统
todo
验证
todo
Cramfs
介绍
Cramfs是Linux的创始人 LinusTorvalds参与开发的一种只读的压缩文件系统。它也基于MTD驱动程序。在cramfs文件系统中,每一页(4KB)被单独压缩,可以随机页访问,其压缩比高达2:1,为嵌入式系统节省大量的Flash存储空间,使系统可通过更低容量的FLASH存储相同的文件,从而降低系统成本。 Cramfs文件系统以压缩方式存储,在运行时解压缩,所以不支持应用程序以XIP方式运行,所有的应用程序要求被拷到RAM里去运行,但这并不代表比Ramfs需求的RAM空间要大一点,因为Cramfs是采用分页压缩的方式存放档案,在读取档案时,不会一下子就耗用过多的内存空间,只针对目前实际读取的部分分配内存,尚没有读取的部分不分配内存空间,当我们读取的档案不在内存时,Cramfs文件系统自动计算压缩后的资料所存的位置,再即时解压缩到RAM中。另外,它的速度快,效率高,其只读的特点有利于保护文件系统免受破坏,提高了系统的可靠性。
由于以上特性,Cramfs在嵌入式系统中应用广泛。但是它的只读属性同时又是它的一大缺陷,使得用户无法对其内容对进扩充。Cramfs映像通常是放在Flash中,但是也能放在别的文件系统里,使用loopback 设备可以把它安装别的文件系统里
制作Cramfs文件系统
todo
Romfs
传统型的Romfs文件系统是一种简单的、紧凑的、只读的文件系统,不支持动态擦写保存,按顺序存放数据,因而支持应用程序以XIP(eXecute In Place,片内运行)方式运行,在系统运行时,节省RAM空间。uClinux系统通常采用Romfs文件系统。
基于RAM的文件系统
Ramdisk
Ramdisk是将一部分固定大小的内存当作分区来使用。它并非一个实际的文件系统,而是一种将实际的文件系统装入内存的机制,并且可以作为根文件系统。将一些经常被访问而又不会更改的文件(如只读的根文件系统)通过Ramdisk放在内存中,可以明显地提高系统的性能。
在Linux的启动阶段,initrd提供了一套机制,可以将内核映像和根文件系统一起载入内存。
ramfs/tmpfs
Ramfs是LinusTorvalds开发的一种基于内存的文件系统,工作于虚拟文件系统(VFS)层,不能格式化,可以创建多个,在创建时可以指定其最大能使用的内存大小。(实际上,VFS本质上可看成一种内存文件系统,它统一了文件在内核中的表示方式,并对磁盘文件系统进行缓冲。) Ramfs/tmpfs文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,可以用ramfs/tmpfs来存储一些临时性或经常要修改的数据,例如/tmp和/var目录,这样既避免了对Flash存储器的读写损耗,也提高了数据读写速度。 Ramfs/tmpfs相对于传统的Ramdisk的不同之处主要在于:不能格式化,文件系统大小可随所含文件内容大小变化。 Tmpfs的一个缺点是当系统重新引导时会丢失所有数据。
网络文件系统NFS (Network File System)
NFS是由Sun开发并发展起来的一项在不同机器、不同操作系统之间通过网络共享文件的技术。在嵌入式Linux系统的开发调试阶段,可以利用该技术在主机上建立基于NFS的根文件系统,挂载到嵌入式设备,可以很方便地修改根文件系统的内容。
以上讨论的都是基于存储设备的文件系统(memory-basedfile system),它们都可用作Linux的根文件系统。实际上,Linux还支持逻辑的或伪文件系统(logical orpseudo file system),例如procfs(proc文件系统),用于获取系统信息,以及devfs(设备文件系统)和sysfs,用于维护设备文件