一. 閃存
我們常說的閃存其實只是一個籠統(tǒng)的稱呼,準確地說它是非易失隨機訪問存儲器(NVRAM)的俗稱,特點是斷電后數(shù)據不消失,因此可以作為外部存儲器使用。而所謂的內存是揮發(fā)性存儲器,分為DRAM和SRAM兩大類,其中常說的內存主要指DRAM,也就是我們熟悉的DDR、DDR2、SDR、EDO等等。閃存也有不同類型,其中主要分為NOR型和NAND型兩大類。
閃存的分類
NOR型與NAND型閃存的區(qū)別很大,打個比方說,NOR型閃存更像內存,有獨立的地址線和數(shù)據線,但價格比較貴,容量比較小;而NAND型更像硬盤,地址線和數(shù)據線是共用的I/O線,類似硬盤的所有信息都通過一條硬盤線傳送一般,而且NAND型與NOR型閃存相比,成本要低一些,而容量大得多。因此,NOR型閃存比較適合頻繁隨機讀寫的場合,通常用于存儲程序代碼并直接在閃存內運行,手機就是使用NOR型閃存的大戶,所以手機的“內存”容量通常不大;NAND型閃存主要用來存儲資料,我們常用的閃存產品,如閃存盤、數(shù)碼存儲卡都是用NAND型閃存。
這里我們還需要端正一個概念,那就是閃存的速度其實很有限,它本身操作速度、頻率就比內存低得多,而且NAND型閃存類似硬盤的操作方式效率也比內存的直接訪問方式慢得多。因此,不要以為閃存盤的性能瓶頸是在接口,甚至想當然地認為閃存盤采用USB2.0接口之后會獲得巨大的性能提升。
前面提到NAND型閃存的操作方式效率低,這和它的架構設計和接口設計有關,它操作起來確實挺像硬盤(其實NAND型閃存在設計之初確實考慮了與硬盤的兼容性),它的性能特點也很像硬盤:小數(shù)據塊操作速度很慢,而大數(shù)據塊速度就很快,這種差異遠比其他存儲介質大的多。這種性能特點非常值得我們留意。
NAND型閃存的技術特點
內存和NOR型閃存的基本存儲單元是bit,用戶可以隨機訪問任何一個bit的信息。而NAND型閃存的基本存儲單元是頁(Page)(可以看到,NAND型閃存的頁就類似硬盤的扇區(qū),硬盤的一個扇區(qū)也為512字節(jié))。每一頁的有效容量是512字節(jié)的倍數(shù)。所謂的有效容量是指用于數(shù)據存儲的部分,實際上還要加上16字節(jié)的校驗信息,因此我們可以在閃存廠商的技術資料當中看到“(512+16)Byte”的表示方式。目前2Gb以下容量的NAND型閃存絕大多數(shù)是(512+16)字節(jié)的頁面容量,2Gb以上容量的NAND型閃存則將頁容量擴大到(2048+64)字節(jié)。
NAND型閃存以塊為單位進行擦除操作。閃存的寫入操作必須在空白區(qū)域進行,如果目標區(qū)域已經有數(shù)據,必須先擦除后寫入,因此擦除操作是閃存的基本操作。一般每個塊包含32個512字節(jié)的頁,容量16KB;而大容量閃存采用2KB頁時,則每個塊包含64個頁,容量128KB。
每顆NAND型閃存的I/O接口一般是8條,每條數(shù)據線每次傳輸(512+16)bit信息,8條就是(512+16)×8bit,也就是前面說的512字節(jié)。但較大容量的NAND型閃存也越來越多地采用16條I/O線的設計,如三星編號K9K1G16U0A的芯片就是64M×16bit的NAND型閃存,容量1Gb,基本數(shù)據單位是(256+??×16bit,還是512字節(jié)。
尋址時,NAND型閃存通過8條I/O接口數(shù)據線傳輸?shù)刂沸畔堪鼈魉?位地址信息。由于閃存芯片容量比較大,一組8位地址只夠尋址256個頁,顯然是不夠的,因此通常一次地址傳送需要分若干組,占用若干個時鐘周期。NAND的地址信息包括列地址(頁面中的起始操作地址)、塊地址和相應的頁面地址,傳送時分別分組,至少需要三次,占用三個周期。隨著容量的增大,地址信息會更多,需要占用更多的時鐘周期傳輸,因此NAND型閃存的一個重要特點就是容量越大,尋址時間越長。而且,由于傳送地址周期比其他存儲介質長,因此NAND型閃存比其他存儲介質更不適合大量的小容量讀寫請求。
二.MTD
MTD是memory technology Device的縮寫。MTD支持類似于內存的存儲器,它是底層硬件和上層軟件之間的橋梁。對底層來說,它無論對nor型或是nandflash都有很好的驅動支持,對上層來說,它抽象出文件系統(tǒng)所需要的接口函數(shù)。同時由于flash自身的特別之處(既有類似塊設備的特點,又有類似字符設備的特點),MTD可以把flash同時為塊設備和字符設備。有了MTD,編寫flash的驅動變得十分輕松,因為上層的架構都已經做好,我們只用看看flash的datasheet,寫最底層的控制時序即可。?
以下內容為翻譯自mtd官方網站http://www.linux-mtd.infradead.org/archive/index.html
mtd致力于為存儲器,尤其是flash,設計一個通用的linux下的子系統(tǒng)。
設計這個系統(tǒng)的目標在于,通過這個系統(tǒng)所提供的硬件驅動和上層系統(tǒng)之間的接口,我們可以方便的為新的硬件編寫驅動。
對于底層的硬件驅動來說,它們所以提供是讀,寫,擦除的流程。而文件的存儲形式是和他們無關的(如FTL,FFS2等等),用恰當?shù)男问酱鎯τ脩舻臄?shù)據那時上層系統(tǒng)關注的事情。
MTD的用戶模塊
MTD為用戶提供五種可以直接在用戶空間使用的模塊
字符設備
塊設備
flash轉換層
nandflash轉換層
JFFS2文件系統(tǒng)
三.yaffs2文件系統(tǒng)
針對于flash的文件系統(tǒng)有很多,據我了解有jffs(1,2,3),yaffs(1,2)。還有商業(yè)的三星開發(fā)的RFS(健壯文件系統(tǒng)),專門針對三星自己的nand和onenand,從底層驅動到上層文件系統(tǒng)一條龍服務,而且號稱和fat格式100%兼容。當時看得我直流口水,心里把三星恨的咬牙切齒。 下面主要介紹一下開源的yaffs文件系統(tǒng)。
Yaffs(Yet Another Flash File System)文件系統(tǒng)是專門針對NAND閃存設計的嵌入式文件系統(tǒng),目前有YAFFS和YAFFS2兩個版本,一般說來,YAFFS對512byte/page以下都有很好的支持,而更大的頁就需要YAFFS2了,如2K/page。
Yaffs文件系統(tǒng)有些類似于JFFS/JFFS2文件系統(tǒng),與之不同的是JFFS1/2文件系統(tǒng)最初是針對NOR FLASH的應用場合設計的,而NOR FLASH和NAND FLASH本質上有較大的區(qū)別,所以盡管JFFS1/2 文件系統(tǒng)也能應用于NAND FLASH,但由于它在內存占用和啟動時間方面針對NOR的特性做了一些取舍,所以對NAND來說通常并不是最優(yōu)的方案。
Yaffs對文件系統(tǒng)上的所有內容(比如正常文件,目錄,鏈接,設備文件等等)都統(tǒng)一當作文件來處理,每個文件都有一個頁面專門存放文件頭,文件頭保存了文件的模式、所有者id、組id、長度、文件名、Parent Object ID等信息。因為需要在一頁內放下這些內容,所以對文件名的長度,符號鏈接對象的路徑名等長度都有限制。
前面說到對于NAND FLASH上的每一頁數(shù)據,都有額外的空間用來存儲附加信息,通常NAND驅動只使用了這些空間的一部分,YAFFS正是利用了這部分空間中剩余的部分來存儲文件系統(tǒng)相關的內容。同時由于支持的page變大,YAFFS2使用更多的spare space來存儲這些信息。在結構上YAFFS和YAFFS2有一定的不同,具體結構可以去看一看這篇文檔http://www.aleph1.co.uk/node/38
那么這個文件系統(tǒng)是如何運作起來呢。
操作文件系統(tǒng)的第一步自然是取得SuperBlock了,Yaffs文件系統(tǒng)本身在NAND Flash上并不存在所謂的SuperBlock塊,完全是在文件系統(tǒng)mount的過程中由read_super函數(shù)填充的,不過有意思的一點是,由于物理上沒有存儲superblock塊,所以NAND Flash上的yaffs文件系統(tǒng)本身沒有存儲filesystem的魔數(shù)(MagicNum),在內存中superblock里的s_magic參數(shù)也是直接賦值的,所以存儲在NAND FLASH上的任何文件系統(tǒng)都能被當作yaffs文件系統(tǒng)mount上來,只是數(shù)據都會被當作錯誤數(shù)據放在lost+found目錄中,不知道這算不算yaffs文件系統(tǒng)的一個bug。
通常一個具體的文件系統(tǒng)在VFS的Super_block結構中除了通用的數(shù)據外,還有自己專用的數(shù)據,Yaffs文件系統(tǒng)的專用數(shù)據是一個yaffs_DeviceStruct結構,主要用來存儲一些相關軟硬件配置信息,相關函數(shù)指針和統(tǒng)計信息等。
在mount過程執(zhí)行read_super的過程中,Yaffs文件系統(tǒng)還需要將文件系統(tǒng)的目錄結構在內存中建立起來。由于沒有super塊,所以需要掃描Yaffs分區(qū),根據從OOB中讀取出的yaffs_tags信息判斷出是文件頭page還是數(shù)據page。再根據文件頭page中的內容以及數(shù)據page中的ObjectID/ChunkID/serial Number等信息在內存中為每個文件(Object)建立一個對應的yaffs_object對象。
在yaffs_object結構中,主要包含了:
??? 如修改時間,用戶ID,組ID等文件屬性;
??? 用作yaffs文件系統(tǒng)維護用的各種標記位如臟(dirty)標記,刪除標記等等;
??? 用作組織結構的,如指向父目錄的Parent指針,指向同級目錄中其他對象鏈表的???? siblings雙向鏈表頭結構
此外根據Object類型的不同(目錄,文件,鏈接),對應于某一具體類型的Object,在Yaffs_object中還有其各自專有的數(shù)據內容
?????? 普通文件:文件尺寸,用于快速查找文件數(shù)據塊的yaffs_Tnode 樹的指針等
?????? 目錄:目錄項內容雙向鏈表頭(children)
?????? 鏈接:softlink的alias,hardlink對應的ObjectID
除了對應于存儲在NAND FLASH上的object而建立起來的yaffs_object以外,在read_super執(zhí)行過程中還會建立一些虛擬對象(Fake Object),這些Fake Object在NAND FLASH上沒有對應的物理實體,比如在建立文件目錄結構的最初,yaffs會建立四個虛擬目錄(Fake Directory):rootDir, unlinkedDir, deleteDir, lostNfoundDir分別用作根目錄,unlinked對象掛接的目錄,delete對象掛接的目錄,無效或零時數(shù)據塊掛接的目錄。
通過創(chuàng)建這些yaffs_object,yaffs文件系統(tǒng)就能夠將存儲在NAND FLASH上數(shù)據系統(tǒng)的組織起來,在內存中維護一個完整的文件系統(tǒng)結構
另外,我在看YAFFS2的源代碼的時候發(fā)現(xiàn),YAFFS2再mount和umount和YAFFS有所區(qū)別,增加一個checkpoint機制,每次在umount的時候,YAFFS2會開辟專門幾個block用來存取一些信息,等待下次mount的時候就不需要掃描整個flash,而只有找出這幾個塊就可以了,這樣可以大大加速mount的時間。不過仔細的原理我也沒有研究過。
?
評論