關於linux下的嵌入式文件係統以及flash文件係統選擇
嵌入式linux下常見的文件係統• RomFS:隻讀文件係統,可以放在ROM空間,也
可以在係統的RAM中,嵌入式linux中常用來作
根文件係統
• RamFS:利用VFS自身結構而形成的內存文件係
統,使用係統的RAM空間
• JFFS/JFFS2:為Flash設計的日誌文件係統
• Yaffs:專門為Nand Flash設計
• proc:為內核和內核模塊將信息發送給進程提
供一種機製,可以查看係統模塊裝載的信息
• devFS:設備文件係統
Linux上的Ext2fs
• 支持4 TB 存儲、文件名稱最長1012 字符
• 可選擇邏輯塊
• 快速符號鏈接
• Ext2不適合flash設備
• 是為象IDE 設備那樣的塊設備設計的,邏輯塊大小必
朧?12 byte、1 KB、2KB等
• 沒有提供對基於扇區的擦除/寫操作的良好管理
• 如果在一個扇區中擦除單個字節,必須將整個扇區複製到
RAM,然後擦除,再重寫入
• 在出現電源故障時,Ext2fs 是不能防止崩潰的
• 文件係統不支持損耗平衡,縮短了flash的壽命
jffs/jffs2文件係統的優缺點
• 日誌文件係統
• 提供了更好的崩潰、掉電安全保護
• jffs2支持對flash的均勻磨損
• 在扇區級別上執行閃存擦除/寫/讀操作要
比Ext2文件係統好
• 文件係統接近滿時,JFFS2 會大大放慢運行
速度——垃圾收集
Nand上yaffs文件係統的優勢
• 專門為Nand flash設計的日誌文件係統
• jffs/jffs2不適合大容量的Nand flash
• jffs的日誌通過jffs_node建立在RAM中,占用
RAM空間:對於128MB的Nand大概需要4MB的空間
來維護節點
• 啟動的時候需要掃描日誌節點,不適合大容量
的Nand flash
• FAT係統沒有日誌
編譯yaffs文件係統
• mtd的最新補丁升級?
• 接口更新,適合與yaffs
• 與原有的mtd驅動程序不兼容,需要重寫
• 如果使用舊mtd驅動需要定義Makefile中
MTD_OLD = -DCONFIG_YAFFS_USE_OLD_MTD
• 參考文檔: yaffs-rootfs-howto
• 最新版的yaffs網站:
https://www.aleph1.co.uk/armlinux/projects/yaffs
使用yaffs文件係統
• 通過cat /proc/yaffs命令可以看到yaffs係
統的相關信息
• mount -t yaffs /dev/mtdblock/0 /mnt/ya
ffs
關於Linux文件係統
JFFS全稱為:The Journalling Flash File System(日誌閃存文件係統)最初由瑞典的 Axis Communications 開發,Red Hat 的 David Woodhouse 對它進行了改進。作為用於微型嵌入式設備的原始閃存芯片的實際文件係統而出現。JFFS文件係統是日誌結構化的,這意味著它基本上是一長列節點。每個節點包含有關文件的部分信息 — 可能是文件的名稱、也許是一些數據。相對於 Ext2 fs,JFFS 因為有以下這些優點而在無盤嵌入式設備中越來越受歡迎:
1 JFFS 在扇區級別上執行閃存擦除/寫/讀操作要比 Ext2 文件係統好。
2 JFFS 提供了比 Ext2 更好的崩潰/掉電安全保護。當需要更改少量數據時,Ext2 文件係統將整個扇區複製到內存(DRAM)中,在內存中合並新數據,並寫回整個扇區。這意味著為了更改單個字,必須對整個扇區(64 KB)執行讀/擦除/寫例程 — 這樣做的效率非常低。要是運氣差,當正在 DRAM 中合並數據時,發生了電源故障或其它事故,那麼將丟失整個數據集合,因為在將數據讀入 DRAM 後就擦除了閃存扇區。JFFS 附加文件而不是重寫整個扇區,並且具有崩潰/掉電安全保護這一功能。
3 這可能是最重要的一點:JFFS 是專門為象閃存芯片那樣的嵌入式設備創建的,所以它的整個設計提供了更好的閃存管理。
要構建JFFS文件係統,首先要有硬件設備FLASH及支持JFFS文件係統的操作係統。
摘要:本文主要分析了uclinux 2.4內核的jffs文件係統機製。希望能對基於uclinux開發產品的廣大工程師有所幫助。
關鍵詞:uclinux vfs jffs
申明:這份文檔是按照自由軟件開放源代碼的精神發布的,任何人可以免費獲得、使用和重新發布,但是你沒有限製別人重新發布你發布內容的權利。發布本文的目的是希望它能對讀者有用,但沒有任何擔保,甚至沒有適合特定目的的隱含的擔保。更詳細的情況請參閱 GNU 通用公共許可證(GPL),以及GNU 自由文檔協議(GFDL)。
你應該已經和文檔一起收到一份GNU 通用公共許可證(GPL)的副本。如果還沒有,寫信給:
The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,MA02139, USA
歡迎各位指出文檔中的錯誤與疑問
一、flash讀寫的特殊性
對於嵌入式係統,flash是很常見的一種設備,而大部分的嵌入式係統都是把文件係統建立在flash之上,由於對flash操作的特殊性,使得在flash上的文件係統和普通磁盤上的文件係統有很大的差別,對flash操作的特殊性包括:
(1) 不能對單個字節進行擦除,最小的擦寫單位是一個block,有時候也稱為一個扇區。典型的一個block的大小是64k。不同的flash會有不同,具體參考flash芯片的規範。
(2) 寫操作隻能對一個原來是空(也就是該地址的內容是全f)的位置操作,如果該位置非空,寫操作不起作用,也就是說如果要改寫一個原來已經有內容的空間,隻能是讀出該sector到ram,在ram中改寫,然後寫整個sector。
由於這些特殊寫,所以在flash這樣的設備上建立文件也有自己獨特的特點,下麵我們就以jffs為例進行分析。
二、jffs體係結構介紹
1、存儲結構
在jffs中,所有的文件和目錄是一樣對待的,都是用一個jffs_raw_inode來表示
整個flash上就是由一個一個的raw inode排列組成,一個目錄隻有一個raw inode,對於文件則是由一個或多個raw inode組成。
2、文件組成
在文件係統mount到flash設備上的時候,會掃描flash,從而根據flash上的所有屬於一個文件的raw inode建立一個jffs_file結構以及node list。
下麵的圖顯示了一個文件的組成
一個文件是由若幹個jffs_node組成,每一個jffs_node是根據flash上得jffs_raw_inode而建立的,jffs_file主要維護兩個鏈表
版本鏈表:主要是描述該node創建的早晚,就是說version_head指向的是一個最老的node,也就意味著垃圾回收的時候最該回收的就是這個最老的node。
區域鏈表:這個鏈表主要是為讀寫文件創建的,version_head指向的node代表的文件數據區域是0~~~n-1 之後依次的節點分別是 n~~~m-1 m~~~~o-1 …….其中n<M<="" p="" />
3、操作
對文件的讀操作應該是比較簡單,但是寫操作,包括更改文件名等操作都是引起一個新的jffs_node的誕生,同時要寫一個相映的raw inode到flash上,這樣的操作有可能導致前麵的某個jffs_node上麵的數據完全失效,從而導致對應flash上的raw inode的空間成為dirty。
下麵舉一個例子可能會更清楚一些。
一個文件的range list是由上麵的三個jffs_node組成,當我們做如下寫操作的時候
lseek( fd, 10, SEEK_SET );
write( fd, buf,40 );
第一個和最後一個node被截短了,第二個node完全被新數據替換,該node會從鏈表上摘下來,flash上空間變成dirty。如果做如下寫操作的時候
lseek( fd, 23, SEEK_SET );
write( fd, buf,5 );
此時,第二個node被分裂成兩個node,同時產生一個新的node,range鏈表的元素變成五個。
基於Linux2.6的YAFFS文件係統移植
v1.0,2005-6-6
一、YAFFS文件係統簡介
YAFFS,Yet Another Flash File System,是一種類似於JFFS/JFFS2的專門為Flash設計的嵌入式文件係統。與JFFS相比,它減少了一些功能,因此速度更快、占用內存更少。
YAFFS和JFFS都提供了寫均衡,垃圾收集等底層操作。它們的不同之處在於:
(1)、JFFS是一種日誌文件係統,通過日誌機製保證文件係統的穩定性。YAFFS僅僅借鑒了日誌係統的思想,不提供日誌機能,所以穩定性不如JAFFS,但是資源占用少。
(2)、JFFS中使用多級鏈表管理需要回收的髒塊,並且使用係統生成偽隨機變量決定要回收的塊,通過這種方法能提供較好的寫均衡,在YAFFS中是從頭到尾對塊搜索,所以在垃圾收集上JFFS的速度慢,但是能延長NAND的壽命。
(3)、JFFS支持文件壓縮,適合存儲容量較小的係統;YAFFS不支持壓縮,更適合存儲容量大的係統。
YAFFS 還帶有NAND芯片驅動,並為嵌入式係統提供了直接訪問文件係統的API,用戶可以不使用Linux中的MTD和VFS,直接對文件進行操作。NAND Flash大多采用MTD+YAFFS的模式。MTD( Memory Technology Devices,內存技術設備)是對Flash操作的接口,提供了一係列的標準函數,將硬件驅動設計和係統程序設計分開。
二、YAFFS文件係統的移植
yaffs代碼可以從https://www.aleph1.co.uk/armlinux/projects/下載(yaffs代碼包括yaffs_ecc
.c,yaffs_fileem.c,yaffs_fs.c,yaffs_guts.c,yaffs_mtdif.c,yaffs_ramem.c。)
表一 Yaffs文件係統源代碼相關文件及功能描述
文件名 功 能
yaffs_ecc.c ECC校驗算法
yaffs_fileem.c 測試flash
yaffs_fs.c 文件係統接口函數
yaffs_guts.c Yaffs文件係統算法
yaffs_mtdif.c NAND函數
yaffs_ramem.c Ramdisk實現
1.內核中沒有YAFFS,所以需要自己建立YAFFS目錄,並把下載的YAFFS代碼複製到該目錄下麵。
#mkdir fs/yaffs
#cp *.c(yaffs source code) fs/yaffs
2.修改fs/Kconfig,使得可以配置yaffs :
source "fs/yaffs/Kconfig"
3.修改fs/makefile,添加如下內容:
obj-$(CONFIG_YAFFS_FS) += yaffs/
4.在fs目錄下生成yaffs目錄,並在裏麵生成一個makefile 和Kconfig
Makefile 內容為:
yaffs-objs := yaffs_fs.o yaffs_guts.o yaffs_mtdif.o yaffs_ecc.o
EXTRA_CFLAGS += $(YAFFS_CONFIGS) -DCONFIG_KERNEL_2_6
Kconfig內容為:
#
# YAFFS file system configurations
#
config YAFFS_FS
tristate "Yet Another Flash Filing System(YAFFS) file system support"
help
YAFFS, for Yet Another Flash Filing System, is a filing system
optimised for NAND Flash chips.
To compile the YAFFS file system support as a module, choose M here:
the module will be called yaffs.
If unsure, say N.
Further information on YAFFS is available at
<https://www.aleph1.co.uk/yaffs/>.
config YAFFS_MTD_ENABLED
bool "NAND mtd support"
depends on YAFFS_FS
help
This adds the yaffs file system support for working with a NAND mtd.
If unsure, say Y.
config YAFFS_RAM_ENABLED
bool "yaffsram file system support"
depends on YAFFS_FS
help
This adds the yaffsram file system support. Nice for testing on x86,
but uses 2MB of RAM. Don't enable for NAND-based targets.
If unsure, say N.
comment "WARNING: mtd and/or yaffsram support should be selected"
depends on YAFFS_FS && !YAFFS_MTD_ENABLED && !YAFFS_RAM_ENABLED
config YAFFS_USE_OLD_MTD
bool "Old mtd support"
depends on YAFFS_FS && 0
help
Enable this to use the old MTD stuff that did not have yaffs support.
You can use this to get around compilation problems, but the best
thing to do is to upgrade your MTD support. You will get better speed.
If unsure, say N.
config YAFFS_USE_NANDECC
bool "Use ECC functions of the generic MTD-NAND driver"
depends on YAFFS_FS
default y
help
This enables the ECC functions of the generic MTD-NAND driver.
This will not work if you are using the old mtd.
NB Use NAND ECC does not work at present with yaffsram.
If unsure, say Y.
config YAFFS_ECC_WRONG_ORDER
bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
depends on YAFFS_FS
help
This makes yaffs_ecc.c use the same ecc byte order as
Steven Hill's nand_ecc.c. If not set, then you get the
same ecc byte order as SmartMedia.
If unsure, say N.
config YAFFS_USE_GENERIC_RW
bool "Use Linux file caching layer"
default y
depends on YAFFS_FS
help
Use generic_read/generic_write for reading/writing files. This
enables the use of the Linux file caching layer.
If you disable this, then caching is disabled and file read/write
is direct.
If unsure, say Y.
config YAFFS_USE_HEADER_FILE_SIZE
bool "Use object header size"
depends on YAFFS_FS
help
When the flash is scanned, two file sizes are constructed:
* The size taken from the object header for the file.
* The size figured out by scanning the data chunks.
If this option is enabled, then the object header size is used,
otherwise the scanned size is used.
If unsure, say N.
config YAFFS_DISABLE_CHUNK_ERASED_CHECK
bool "Turn off debug chunk erase check"
depends on YAFFS_FS
default y
help
Enabling this turns off the test that chunks are erased in flash
before writing to them. This is safe, since the write verification
will fail. Suggest enabling the test (ie. say N)
during development to help debug things.
If unsure, say Y.
#config YAFFS_DISABLE_WRITE_VERIFY
# bool "Disable write verify (DANGEROUS)"
# depends on YAFFS_FS && EXPERIMENTAL
# help
# I am severely reluctant to provide this config. Disabling the
# verification is not a good thing to do since NAND writes can
# fail silently. Disabling the write verification will cause your
# teeth to rot, rats to eat your corn and give you split ends.
# You have been warned. ie. Don't uncomment the following line.
#
# If unsure, say N.
#
config YAFFS_SHORT_NAMES_IN_RAM
bool "Cache short names in RAM"
depends on YAFFS_FS
default y
help
If this config is set, then short names are stored with the
yaffs_Object. This costs an extra 16 bytes of RAM per object,
but makes look-ups faster.
If unsure, say Y.
5.在/arch/arm/mach-s3c2410/mach-smdk2410.c找到smdk_default_nand_part結構,修改nand分區,如下:
struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "vivi",
.size = 0x00020000,
.offset = 0x00000000,
},
[1] = {
.name = "param",
.size = 0x00010000,
.offset = 0x00020000,
},
[2] = {
.name = "kernel",
.size = 0x00100000,
.offset = 0x00030000,
},
[3] = {
.name = "root",
.size = 0x01900000,
.offset = 0x00130000,
},
[4] = {
.name = "user",
.size = 0x025d0000,
.offset = 0x01a30000,
}
};
注:此分區要結合vivi裏麵的分區來進行設置。
6.配置內核時選中MTD支持:
Memory Technology Devices (MTD) --->
<*> Memory Technology Device (MTD) support
MTD partitioning support
……
--- User Modules And Translation Layers
<*> Direct char device access to MTD devices
<*> Caching block device access to MTD devices
……
NAND Flash Device Drivers --->
<*> NAND Device Support
<*> NAND Flash support for S3C2410 SoC
S3C2410 NAND driver debug
7.配置內核時選中YAFFS支持:
File systems --->
Miscellaneous filesystems --->
<*> Yet Another Flash Filing System(YAFFS) file system support
NAND mtd support
Use ECC functions of the generic MTD-NAND driver
Use Linux file caching layer
Turn off debug chunk erase check
Cache short names in RAM
8.編譯內核並將內核下載到開發板的flash中。
三、Yaffs文件係統測試:
1.內核啟動之後,在啟動信息裏麵可以看到如下內容:
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
Scanning device for bad blocks
Creating 5 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00020000 : "vivi"
0x00020000-0x00030000 : "param"
0x00030000-0x00130000 : "kernel"
0x00130000-0x01a30000 : "root"
0x01a30000-0x04100000 : "user"
2.如果在內核裏麵添加了proc文件係統的支持那麼你在proc裏麵可以看到有關yaffs的信息
~ # cat proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
nodev proc
nodev sockfs
nodev pipefs
nodev futexfs
nodev tmpfs
nodev eventpollfs
nodev devpts
nodev ramfs
vfat
nodev devfs
nodev nfs
yaffs
nodev rpc_pipefs
3.查看dev目錄下相關目錄可以看到:
~ # ls dev/mtd -al
drwxr-xr-x 1 root root 0 Jan 1 00:00 .
drwxr-xr-x 1 root root 0 Jan 1 00:00 ..
crw-rw-rw- 1 root root 90, 0 Jan 1 00:00 0
cr--r--r-- 1 root root 90, 1 Jan 1 00:00 0ro
crw-rw-rw- 1 root root 90, 2 Jan 1 00:00 1
cr--r--r-- 1 root root 90, 3 Jan 1 00:00 1ro
crw-rw-rw- 1 root root 90, 4 Jan 1 00:00 2
cr--r--r-- 1 root root 90, 5 Jan 1 00:00 2ro
crw-rw-rw- 1 root root 90, 6 Jan 1 00:00 3
cr--r--r-- 1 root root 90, 7 Jan 1 00:00 3ro
crw-rw-rw- 1 root root 90, 8 Jan 1 00:00 4
cr--r--r-- 1 root root 90, 9 Jan 1 00:00 4ro
~ # ls dev/mtdblock/ -al
drwxr-xr-x 1 root root 0 Jan 1 00:00 .
drwxr-xr-x 1 root root 0 Jan 1 00:00 ..
brw------- 1 root root 31, 0 Jan 1 00:00 0
brw------- 1 root root 31, 1 Jan 1 00:00 1
brw------- 1 root root 31, 2 Jan 1 00:00 2
brw------- 1 root root 31, 3 Jan 1 00:00 3
brw------- 1 root root 31, 4 Jan 1 00:00 4
4.mount、umount
建立mount目錄
~ #mkdir /mnt/flash0
~ #mkdir /mnt/flash1
Mountblockdevice設備
~ #mount –t yaffs /dev/mtdblock/3 /mnt/flash0
~ #mount –t yaffs /dev/mtdblock/4 /mnt/flash1
~ #cp 1.txt /mnt/flash0
~ #cp 2.txt /mnt/flash1
查看mount上的目錄,可以看到該目錄下有剛才拷貝的文件,將其umount後,再次mount上來可以發現拷貝的文件仍然存在,這時刪除該文件然後umount,再次mount後,可以發現拷貝的文件已經被刪除,由此可以該分區可以正常讀寫。
5.在flash上建立根文件係統
~ # mount –t yaffs /dev/mtdblock/3 /mnt/flash0
~ #cp (your rootfs) /mnt/flash0
~ #umount /mnt/flash0
重新啟動,改變啟動參數:
param set linux_cmd_line "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
重新啟動,開發板就可以從flash啟動根文件係統了。
注:這裏你得在內核中添加devfs文件係統的支持,否則內核無法找到/dev/mtdblock/3目錄
目前flash的文件係統比較多,用的比較多的就是JFFS2文件係統。基於NOR flash上的JFFS2文件係統可以說算是比較成熟了,支持NAND flash的JFFS2也已經發布了。源代碼可以到https://www.linux-mtd.infradead.org上麵下載。但是在我的測試過程中,在nand
flash上掛接的JFFS2文件係統很不穩定,經常有CRC錯誤產生。特別是進行寫操作的時候,每次複位都會產生CRC錯誤,可以說支持NAND flash的JFFS2文件係統目前還不成熟。而YAFFS文件係統則是專門針對NAND flash的,源代碼可以到
https://www.aleph1.co.uk/yaffs/index.html上下載。在測試過程中穩定性能比JFFS2文件係統要穩定的多,而且mount分區的時間也比JFFS2文件係統少的多。用JFFS2 mount一個2m的文件係統大約需要1s。下麵分別介紹在uclinux下麵使用JFFS2和YAFFS文件係統。
1、JFFS2
到https://www.linux-mtd.infradead.org上麵下載最新的MTD和JFFS2壓縮包。壓縮包裏麵還有有關的內核補丁和一些MTD的相關工具。主要的補丁就是ilookup-2.4.23.patch,因為最新的MTD驅動中要用到一個ilookup()函數。打完補丁、更新了MTD驅動和JFFS2文件係統之後就開始寫自己nand
flash驅動了。如果不想把JFFS2作為根文件係統的話,還需要修改MTD_BLOCK_MAJOR。驅動可以參考裏麵的例子,最簡單的就是參考spia.c。
寫驅動主要工作是定義flash分區結構、定義flash讀寫地址、寫控製flash的**_hwcontrol()函數。具體的操作要看所用的nand flash的芯片資料。相對NOR flash來說驅動要簡單多了。:)
改完之後再配置
Memory Technology Devices(MTD)下
CONFIG_MTD=Y
CONFIG_MTD_DEBUG=Y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_PARTITIONS=Y
CONFIG_MTD_CHAR=Y
CONFIG_MTD_BLOCK=Y
NAND Flash Device Drivers下
CONFIG_MTD_NAND=Y
定義自己的驅動文件
File systems下
CONFIG_JFFS2_FS=Y
CONFIG_JFFS2_FS_DEBUG=2
CONFIG_JFFS2_FS_NAND=y /*這個是新加的*/
在uClinux v1.3.4 Configuration下
Flash Tools下
CONFIG_USER_MTDUTILS=Y
CONFIG_USER_MTDUTILS_ERASE=Y
CONFIG_USER_MTDUTILS_ERASEALL=Y
CONFIG_USER_MTDUTILS_MKFSJFFS2=Y
最後就是辛苦了調試工作了。:(MTD驅動調試完之後,就可以在上麵掛接JFFS2文件係統了。參看flash分區情況:cat /proc/mtd,擦除分區:eraseall /dev/mtd*.例如把第一個分區mount到/mnt目錄下麵:
先:eraseall /dev/mtd0
然後:mount -t jffs2 /dev/mtdblock0 /mnt
2、YAFFS
YAFFS意義為'yet another flash file system',也是一個開源的文件係統。YAFFS是目前為止唯一一個專門為NAND flash設計的文件係統,具有很好的可移植性,能夠在linux,uclinux,和wince
下麵運行。
在https://www.aleph1.co.uk/yaffs/index.html上下載源代碼。壓縮包裏麵也包含YAFFS的說明文檔。YAFFS文件係統的源文件就devextras.h,yaffs_ecc.c,yaffs_ecc.h,yaffs_guts.c,yaffs_guts.h,yaffs_mtdif.h,yaffs_mtdif.c和yportenv.h
另外需要配置的宏:CONFIG_YAFFS_FS 和CONFIG_YAFFS_MTD_ENABLED,就是配置在mtd上麵掛接YAFFS,其它還有一些輔助配置需要時也可以配置。
在fs目錄下麵建一個yaffs目錄,把以上說的文件考裏麵去,新建一個makefile:
O_TARGET := yaffs.o
obj-y := yaffs_fs.o yaffs_guts.o yaffs_mtdif.o yaffs_ecc.o
obj-m := $(O_TARGET)
include $(TOPDIR)/Rules.make
接下來就是改fs目錄下麵config.in和makefile,在配置YAFFS的時候,把YAFFS連接進去。
如果像前麵一樣已經把NAND MTD驅動調好了,加YAFFS就很簡單了。因為YAFFS是自己做ECC校驗的,所以要把MTD驅動裏麵的ECC去掉。在驅動裏麵改成this->eccmode = NAND_ECC_NONE就可以了。
另外YAFFS是用mkyaffs來擦除flash,所以在mtd-utils中加上mkyaffs.c,一起編譯進去。
最後就是編譯了,嗬嗬。中間會有一些警告沒有關係的,就是寫沒有用的變量和函數,不過話說回來YAFFS的代碼寫的確實不太規範。當然它的性能確實沒話說。有興趣的可以試一下。
最後更新:2017-04-03 12:53:57