YAFFS2文件系統在嵌入式LINUX系統中的應用
1.文件系統簡述
隨著32位CPU價格不斷下跌,片上存儲設備的容量相比越來越大,越來越多的嵌入式系統開始應用各種嵌入式操作系統。一般在嵌入式領域,只要應用到操作系統的必然會需要一個,甚至是多個文件系統。所謂文件系統,實際上就是在一個具體的存儲設備上任何文件的組織和目錄。這個設備可能是各種RAM、NAND FLASH、NOR FLASH等DOC設備,還有以NAND FLASH 為基礎的各種存儲卡等[1]。目前,針對不同的設備和應用有很多文件系統可供選擇,例如EXT2、TEMPFS、RAMDISK、CRAMFS、 JFFS1/2、YAFFS1/2、XFS等。除此之外,還有很多供應商提供的商用文件系統。
選擇文件系統,要根據具體應用的需求。一般,首先要考慮的就是可靠性,健壯性和增強的需求。如果是像工控這樣的不需經常更新控制程序的應用來說,我們選擇CARAMFS這樣的只讀文件系統已經足夠了,而且它還可以帶來的另外一個好處就是 CRAMFS的壓縮率高達50%,可以大大節省我們的存儲空間。但是如果是像涉及到數據采集這類需要保存數據的應用來說,只讀的文件系統就很難滿足應用系統的需求,我們可以選擇JFFS或者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 操作的接口,提供了一系列的標準函數,將硬件驅動設計和系統程序設計分開。
YAFFS2 是 YAFFS 的升級版,能更好的支持 NAND FLASH ,我們采用最新的 YAFFS2 文件系統。我們首先下載 YAFFS 文件系統。http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/yaffs2.tar.gz?view=tar
?
2.文件系統的實現
2.1文件系統的選擇
在本文涉及的應用中,根文件系統并不需要頻繁的更改,但是卻涉及到一些數據的存取。考慮到的存儲設備是NAND FLASH,所以在根文件系統格式的選擇上可以用壓縮率比較高的CRAMFS,而在根文件系統下掛載一個可讀寫的YAFFS2文件系統。
YAFFS2(Yet Another nandFlash FileSytem2)是專門針對NAND設備的一種文件系統。YAFFS2類似于JFFS/JFFS2文件系統,與YAFFS2不同的是JFFSS1 /2文件系統最初是針對NOR FLASH的應用場合設計的。而YAFFS2針對NAND FLASH的特點采用增強的碎片回收和均衡磨損技術,大大提高了讀寫速度,延長了存儲設備的使用壽命[2],可以更好的支持大容量的NAND FLASH芯片。而且在斷電可靠性上,YAFFS2的優勢更加明顯[3]。
?
???????? 2.2建立根文件系統
Linux內核啟動以后,根據參數linux_cmd_line的指示跳轉到根文件系統的地址,完成文件系統的初始化和掛載任務。根文件系統的建立可以借助各種開發套件來完成,也可以完全由自己搭建一個。這里介紹如何通過開發套件的幫助來完成基本的根文件系統。Busybox是由Bruce Perens發起的一項計劃,該計劃最初的目的是協助Debian發行套件建立安裝磁盤。由于Busybox小巧但功能不失強大,所以在嵌入式系統中有很廣的應用。下載Busybox穩定版(www.busybox.net),解壓后直接make menuconfig 進入Busybox配置菜單,這個界面根內核差不多。在Applets下面選擇你需要命令,然后退出保存, 執行make , make install。在Busybox的目錄下就會生成_install目錄,這個目錄就包含了將要配置的命令的工具包。把這個目錄拷貝到工作目錄,更名為 rootfs, 這個目錄就是要建立的根文件系統的雛形——但是它還不能工作,需要進一步的完善。
在rootfs/下,首先在/rootfs/dev下建立必須的設備文件。關于設備的建立,可以參考Filesystem Hierarchy Standard來確定需要的哪些設備文件(http://www.pathname.com/fhs/)。下一步就是完成/rootfs/etc這個目錄下的3個比較重要的文件inittab,fstab,init.d/rcS(或者是rc.d/rc.sysinit,這個由inittab決定)。下面給出可供參考的樣例:
Inittab文件
#System initialization .
::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
::restart:/sbin/init
::shutdown:/bin/umount –a –r
::shutdown:/sbin/swapoff –a
?
Fstab文件
none??? /proc?? proc?? defaults???? 0?? 0
tmpfs?? /temp??? tmfs?? defaults???? 0?? 0
fstab指定了設備的掛載點。要了解關于fstab文件的格式以及詳細信息,可以參考
http://www.tuxfiles.org/linuxhelp/fstab.html
?
Init.d/rcS文件
#!/bin/sh
Mount –o remount, rw /
/bin/mount –a
>/etc/mtab
Echo? “messages”
Hostname? “hostname”
在這個腳本中,還可以定義內核的其他一些動作,這在后面掛載YAFFS2文件系統中顯得非常有用。
最后,加入需要的鏈接庫文件就可以了。通常這部分會比較麻煩,因為你并不知道你的應用具體需要哪些庫文件,可以通過兩種途徑解決這個問題:一是利用工具readelf來找出應用程序依存哪些鏈接庫;二是參考linux相關計劃網站上的提供的文件系統,來確定需要的鏈接庫文件[4]。
?
2.3制作YAFFS2文件系統
根文件系統做好后,可以通過NFS(http://nfs.sourceforge.net/nfs-howto/ )來測試文件系統是否可行,但是最后我們還是要把這個文件系統燒進目標板。
可以有兩種方式來應用YAFFS2文件系統,一是CRAMFS+YAFFS2的組合,一種是純YAFFS2文件系統格式 。由于在筆者的應用中,內核和根文件系統并不需要頻繁更新,所以從節省存儲空間和保護根文件系統的角度來考慮,我們選用CRAMFS這樣的高壓縮率、只讀文件系統,而應用程序,用戶空間使用YAFFS2文件系統格式。
對于CRAMFS,可以直接用mkcramfs? /rootfs? ~/root.img來制作cramfs鏡像,/rootfs是前面建立的根文件系統目錄,~/root.img指定做好鏡像的保存目錄。由于 YAFFS2文件系統當初設計就是針對nand設備的,在筆者的應用中,文件系統是在NANDFLASH中啟動,因此要使用YAFFS2文件系統,就必須先在內核添加NAND設備驅動[5],并修改arch/arm/mach-s3c2410/devs.c文件,增加nand flash分區。一般情況下bootloader, kernel, root 三個分區是必須的,也有的加了param分區來保存內核參數,user分區來作為用戶空間的,但是也可以不要。
在www.aleph.co.uk 下載YAFFS2(GPL)源碼,解壓后在YAFFS2目錄下執行
patch-ker.sh? ~/Linux2.6.14.2
~/Linux2.6.14.2是內核的路徑,筆者的內核是2.6.14.2。patch后在內核的fs目錄下就會生成yaffs2目錄,這樣內核就已經得到YAFFS2的支持了。
接下來make menuconfig ,配置內核時在
Device Drivers->
Memory Technology Device (MTD)->
下選中MTD Partitioning Surpport,這樣我們的分區信息才有效。在
File System->
Miscellaneous filesystems->下配置YAFFS2如下:
?
<>EFS file system support(read only) (EXPERIMENTAL)
<*>YAFFS2 file system support
--- 512 byte / page devices
[*]Lets Yaffs do its own ECC
[*]Use the same ecc byte order as Steven Hill’s nand_ecc.c
--- 2048 byte (or larger) / page devices
[*]Autoselect yaffs2 format
[*]Disable lazy loading
[*]Turn off wide tnodes
[*]Turn off debug chunk erase check
[*]Cache short names in RAM
<>Jounalling Flash File System (JFFS) support
?
保存配置,退出,執行make。Make結束后就得到了一個具備掛載yaffs2文件系統能力的內核鏡像 。
在bootloader源文件中,將nand flash分成幾個分區,前面提到的devs.c文件里的分區也必須與bootloader的分區一致 ,因為bootloader指定了內核和文件系統的地址,最后啟動時也會到相應的地址尋找指令。在我們的應用中,將flash分成bootloader, param, kernel, root, user。其中root用來掛載CRAMFS根文件系統,user分區掛載YAFFS2文件系統。
在YAFFS2源文件的utils目錄下,執行make就可以生成 mkyaffs2image工具,執行
./mkyaffs2image (要制作yaffs2的目錄) (目標鏡像)
生成yaffs2文件系統,不過因為前面根文件系統是CRAMFS格式,YAFFS2可以作為模塊來加載,這樣更加方便,更加靈活。加載模塊也可以在后面給出的腳本中定義。
最后一步就是要讓內核在啟動后掛載文件系統,掛載文件系統有兩種方式:手動和自動掛載。在實際應用中當然是要系統在無需人工干預的情況下自動掛載文件系統。在Debian系統中,初始化腳本是/etc/init.d/rcS,在Rad Hat中是/etc/rc.d/rc.sysinit。這里面包含了裝入文件系統,設置時間,打開交換分區,得到主機名等等內容。回顧前面給出的 Inittab和init.d/rcS文件就知道,系統的Init進程是如何動作的。對照前面的rcS文件這里給出一個更加詳細的并給出注釋。
#! /bin/sh???????????????????????????????????? //busybox提供的SHELL
?
PATH=/sbin:/bin:/usr/sbin:/usr/bin???????????? //設置系統路徑
runlevel=S???????????????? ????????????????????//運行級別
prevlevel=N???????????????????????????????????????
umask 022????????????????????????????????????? //缺省訪問權限為022
export PATH runlevel prevlevel
?
/bin/mount -f -t cramfs -o remount,ro /dev/mtdblock/3 /
??????????????????????????? ?????????????????//cramfs作為根文件系統掛到第四個分區下,即root分區。
/sbin/insmod -f /lib/yaffs2.ko???????????????? //加載yaffs2模塊
/sbin/mount -t yaffs2 /dev/mtdblock/4 /usr?????? //yaffs2掛到第五個分區,作為/usr
?
/sbin/mount -t proc none /proc?? ??????????????//mount命令由busybox提供
/sbin/mount -t tmpfs none /root??????????????? //掛載tmpfs到指定目錄,下同
?
/sbin/mount -t tmpfs none /tmp
/sbin/mount -t tmpfs none /var
?
/sbin/mkdir -p /var/lib???????????????????????? //創建目錄
/sbin/mkdir -p /var/run
/sbin/mkdir -p /var/log
?
/etc/rc.d/init.d/leds start??????????????????? //初試用戶程序leds
?
/sbin/ifconfig lo 127.0.0.1??????????????????? //指定lo設備的IP地址為127.0.0.1
#/sbin/ifconfig eth0 192.168.0.2
?
/sbin/hostname -F /etc/sysconfig/HOSTNAME?????? //指定主機名文件路徑.
?
將文件系統燒進目標板對應分區,boot,即可運行。至此,目標板可以通過/usr進行讀寫文件,目標板完成對yaffs2的支持。