來源: http://sites.google.com/site/rgbbones2/yaffs

1 Yaffs文件系統結構

1.1 簡介

1.1.1 應用場合

        Yaffs(Yet Another Flash File System)文件系統是專門針對NAND閃存設計的嵌入式文件系統,目前有YAFFS和YAFFS2兩個版本,兩個版本的主要區別之一在於YAFFS2能夠更好的支持大容量的NAND FLASH芯片。
Yaffs文件系統有些類似於JFFS/JFFS2文件系統,與之不同的是JFFS1/2文件系統最初是針對NOR FLASH的應用場合設計的,而NOR FLASH和NAND FLASH本質上有較大的區別,所以儘管JFFS1/2 文件系統也能應用於NAND FLASH,但由於它在內存佔用和啟動時間方面針對NOR的特性做了一些取捨,所以對NAND來說通常並不是最優的方案。

1.1.2 NOR和NAND的比較

        基本上NOR比較適合存儲程序代碼,其容量一般較小(比如小於32MB),價格較高,而NAND容量可達1GB以上,價格也相對便宜,適合存儲數據。一般來說,128MB以下容量NAND FLASH 芯片的一頁大小為528字節,用來存放數據,另外每一頁還有16字節的備用空間(SpareData,OOB),用來存儲ECC校驗/壞塊標誌等信息,再由若干頁組成一個塊,通常一塊為32頁16K。
        與NOR相比,NAND不是完全可靠的,每塊芯片出廠時都有一定比例的壞塊存在,對數據的存取不是使用地址映射而是通過寄存器的操作,串行存取數據。

1.2 Yaffs文件系統數據在NAND上的存儲方式

        Yaffs對文件系統上的所有內容(比如正常文件,目錄,鏈接,設備文件等等)都統一當作文件來處理,每個文件都有一個頁面專門存放文件頭,文件頭保存了文件的模式、所有者id、組id、長度、文件名、Parent Object ID等信息。因為需要在一頁內放下這些內容,所以對文件名的長度,符號鏈接對象的路徑名等長度都有限制。
前面說到對於NAND FLASH上的每一頁數據,都有額外的空間用來存儲附加信息,通常NAND驅動只使用了這些空間的一部分,Yaffs正是利用了這部分空間中剩餘的部分來存儲文件系統相關的內容。以512+16B為一個PAGE的NAND FLASH芯片為例,Yaffs文件系統數據的存儲佈局如下所示:

0..511

數據區域

512..515

YAFFS TAG

516

Data status byte

517

Block status byte 壞塊標誌位

518..519

YAFFS TAG

520..522

256字節數據的ECC校驗結果

523..524

YAFFS TAG

525..527

256字節數據的ECC校驗結果

        可以看到在這裡YAFFS一共使用了8個BYTE用來存放文件系統相關的信息(yaffs_Tags)。這8個Byte的具體使用情況按順序如下:

Bits

Content

20

ChunkID,該page在一個文件內的索引號,所以文件大小被限制在2^20 PAGE 512Mb

2

2 bits serial number

10

ByteCount page內的有效字節數

18

ObjectID 對象ID號,用來唯一標示一個文件

12

Ecc, Yaffs_Tags本身的ECC校驗和

2

Unused

  其中Serial Number在文件系統創建時都為0,以後每次寫具有同一ObjectID和ChunkID的page的時候都加一,因為Yaffs在更新一個PAGE的時候總是在一個新的物理Page上寫入數據,再將原先的物理Page刪除,所以該serial number可以在斷電等特殊情況下,當新的page已經寫入但老的page還沒有被刪除的時候用來識別正確的Page,保證數據的正確性。
        ObjectID號為18bit,所以文件的總數限制在256K即26萬個左右。
        最後以上這些是針對Yaffs1而言,對於Yaffs2因為針對chunk size大於1k的NAND FLASH,在Tags各份量及總體尺寸上都做了修改,以便更快更好的處理大容量的NAND FLASH芯片。由於Tag尺寸的增大,在512+16B類型的NAND FLASH上就一個Trunk對應一個page的情況,目前就無法使用Yaffs2文件系統了。
        由於文件系統的基本組織信息保存在頁面的備份空間中,因此,在文件系統加載時只需要掃瞄各個頁面的備份空間,即可建立起整個文件系統的結構,而不需要像JFFS1/2 那樣掃瞄整個介質,從而大大加快了文件系統的加載速度。


1.3 yaffs文件系統在內存中的組織方式

1.3.1 SupperBlock

        操作文件系統的第一步自然是取得SuperBlock了,Yaffs文件系統本身在NAND Flash上並不存在所謂的SuperBlock塊,完全是在文件系統mount的過程中由read_super函數填充的,不過有意思的一點是,由於物理上沒有存儲superblock塊,所以NAND Flash上的yaffs文件系統本身沒有存儲filesystem的魔數(MagicNum),在內存中superblock裡的s_magic參數也是直接賦值的,所以存儲在NAND FLASH上的任何文件系統都能被當作yaffs文件系統mount上來,只是數據都會被當作錯誤數據放在lost+found目錄中,不知道這算不算yaffs文件系統的一個bug。
        通常一個具體的文件系統在VFS的Super_block結構中除了通用的數據外,還有自己專用的數據,Yaffs文件系統的專用數據是一個yaffs_DeviceStruct結構,主要用來存儲一些相關軟硬件配置信息,相關函數指針和統計信息等。

1.3.2 文件在內存中的組織方式

        在mount過程執行read_super的過程中,Yaffs文件系統還需要將文件系統的目錄結構在內存中建立起來。由於沒有super塊,所以需要掃瞄Yaffs分區,根據從OOB中讀取出的yaffs_tags信息判斷出是文件頭page還是數據page。再根據文件頭page中的內容以及數據page中的ObjectID/ChunkID/serial Number等信息在內存中為每個文件(Object)建立一個對應的yaffs_object對象。
        在yaffs_object結構中,主要包含了:

    Ø 如修改時間,用戶ID,組ID等文件屬性;
    Ø 用作yaffs文件系統維護用的各種標記位如髒(dirty)標記,刪除標記等等;
    Ø 用作組織結構的,如指向父目錄的Parent指針,指向同級目錄中其他對象鏈表的siblings雙向鏈表頭結構
    
        此外根據Object類型的不同(目錄,文件,鏈接),對應於某一具體類型的Object,在Yaffs_object中還有其各自專有的數據內容
    Ø 普通文件:文件尺寸,用於快速查找文件數據塊的yaffs_Tnode 樹的指針等
    Ø 目錄:目錄項內容雙向鏈表頭(children)
    Ø 鏈接:softlink的alias,hardlink對應的ObjectID

        除了對應於存儲在NAND FLASH上的object而建立起來的yaffs_object以外,在read_super執行過程中還會建立一些虛擬對象(Fake Object),這些Fake Object在NAND FLASH上沒有對應的物理實體,比如在建立文件目錄結構的最初,yaffs會建立四個虛擬目錄(Fake Directory):rootDir, unlinkedDir, deleteDir, lostNfoundDir分別用作根目錄,unlinked對象掛接的目錄,delete對象掛接的目錄,無效或零時數據塊掛接的目錄。
        通過創建這些yaffs_object,yaffs文件系統就能夠將存儲在NAND FLASH上數據系統的組織起來,在內存中維護一個完整的文件系統結構。

2 Yaffs文件系統集成及應用相關

2.1 系統移植

        這裡所謂移植,就是在特定的軟硬件環境裡編譯出yaffs文件系統模塊了。目前最新的yaffs版本的代碼裡主要是按照2.6內核的方式寫的Kconfig和Makefile,對於2.4內核來說,改起來也很簡單,基本上,只需要:

    Ø 在內核中建立YAFFS目錄fs/yaffs,並把下載的YAFFS代碼複製到該目錄下面。
    Ø 參考yaffs代碼中的Kconfig文件,按照2.4內核的風格修改你自己的Config.in文件,使得可以配置YAFFS。
    Ø 修改fs/makefile,加入yaffs目錄
    Ø 按照2.4內核的風格修改YAFFS目錄中的Makefile文件。

        只是在配置YAFFS的時候需要注意一點,即使你的NAND FLASH是512+16B的,不需要使用YAFFS2,也需要將對2k page的NAND FLASH的支持這一項選上,否則編譯無法通過(因為部分代碼沒有用CONFIG宏包起來),不知道這是不是我下載的這個版本的個別現象,還是對Makefile還需要進一步的修改。
        此外就是最好把Lets Yaffs do its own ECC選上,理由後面會說,其他選項就無所謂了,主要是對性能的調整,看著選吧,按推薦配置好了,比如Turn off debug chunk erase check,這一項,我試驗的結果選上後平均可以提高20-30%左右的擦寫速度。

2.2 Yaffs文件系統的製作和使用

2.2.1 通過Yaffs Image文件製作yaffs文件系統

        Yaffs源代碼包的utils目錄下包含了mkyaffsimage/mkyaffs2image的代碼,簡單的修改一下Makefile裡的內核路徑就能編譯出mkyaffsimage/mkyaffs2image工具。
        運行mkyaffsimage dir imagename可以製作出yaffs1文件系統的鏡像。
        但是,需要注意的是,製作出來的yaffs image文件與通常的文件系統的image文件不同,因為在image文件裡除了以512字節為單位的一個page的data數據外,同時緊跟在後還包括了16字節為單位的NAND備份數據區(OOB)的數據。所以實際上是以528個字節為單位的。就是因為包含了這額外的16字節/page的數據,所以基本上常規辦法如dd,或者通常的下載其它類型image的工具就無法正常下載yaffs image了,需要修改你所使用的下載工具的代碼,使得它能將yaffs image中的這些額外數據也寫入NAND FLASH OOB中。
        這裡還有一點需要注意的是,通過mkyaffsimage製做出來的image其OOB中也包含它自己計算的ECC校驗數據,其校驗算法有可能和MTD NAND驅動的校驗算法不同,如果在內核中由MTD來處理ECC,會造成MTD認為所有的page都校驗錯誤。所以,這也是我前面說最好把Lets Yaffs do its own ECC選上的原因,同時,要把MTD NAND驅動中的ECC校驗關閉。

2.2.2 其它方式製作yaffs文件系統

        如果不考慮產線批量下載的話,也可以通過mount拷貝的方式準備yaffs文件系統。用flash_eraseall將NAND FLASH分區擦除,然後做為yaffs分區直接mount上來,將文件系統的內容拷貝上去就可以了。這可能是在真正的NAND FLASH上試驗yaffs文件系統最簡單的方式了。

2.2.3 沒有相應的NAND設備時如何測試yaffs文件系統

        沒有相應的NAND FLASH設備包含兩種情況:

    Ø 硬件上沒有NAND FLASH,開發板上沒有或者想在主機環境中測試yaffs文件系統
    Ø 沒有合適的page size的NAND FLASH芯片,比如板上NAND FLASH芯片為512+16的格式,但是想要試驗Yaffs2文件系統。
        Yaffs提供了兩種用來在這種情況下測試yaffs文件系統的途徑。

2.2.3.1 Nandemul

        Yaffs source包裡包含了mtdemul目錄,Yaffs2中該目錄下的文件主要是Nandemul2k.c用來模擬2K page size的NAND FLASH。在Yaffs中則是Nandemul.c用來模擬512字節page size的NAND FLASH。
        稍微修改一下Makeflie將編譯出來的模塊插入內核,將在/dev/mtd /dev/mtdblock目錄下創建一個新的MTD設備。然後就可以將該設備當作一個物理的MTD NAND設備分區進行相關的操作,可以在上面創建yaffs文件系統,mount umount等等。這種方法不僅適用於yaffs文件系統,同樣也適用於其它可用於NAND設備的文件系統。

2.2.3.2 Yaffsram

        根據yaffs 官方文檔的描述,通過mount –t yaffsram none /mountpoint 可以在內存中建立一個yaffs分區,這有些類似於ramfs。不過,在試驗最新版本的Yaffs2文件系統時,該功能並不可用,只有Yaffs1文件系統的代碼包裡包含了相關的代碼。

 

huenlil 發表在 痞客邦 PIXNET 留言(0) 人氣()