Flash文件系統剖析
您之前可能聽(tīng)說(shuō)過(guò) Journaling Flash File System(JFFS)和 Yet Another Flash File System(YAFFS),但是您知道使用底層 flash 設備的文件系統意味著(zhù)什么嗎?本文將向您介紹 Linux® 的 flash 文件系統,并探索它們如何通過(guò)平均讀寫(xiě)(wear leveling)處理底層的可消耗設備(flash 部件),并鑒別各種不同的 flash 文件系統以及它們的基本設計。
本文引用地址:http://dyxdggzs.com/article/257951.htm固態(tài)驅動(dòng)器當前非常流行,但是嵌入式系統很久以前就開(kāi)始使用固態(tài)驅動(dòng)器進(jìn)行存儲。您可以看到 flash 系統被用于個(gè)人數字助理(PDA)、手機、MP3 播放器、數碼相機、USB flash 驅動(dòng)(UFD),甚至筆記本電腦。很多情況下,商業(yè)設備的文件系統可以進(jìn)行定制并且是專(zhuān)有的,但是它們會(huì )遇到以下挑戰。
基于 Flash 的文件系統形式多種多樣。本文將探討幾種只讀文件系統,并回顧目前可用的各種讀/寫(xiě)文件系統及其工作原理。但是,讓我們先看看 flash 設備及其所面對的挑戰。
Flash 內存技術(shù)
Flash 內存(可以通過(guò)幾種不同的技術(shù)實(shí)現)是一種非揮發(fā)性?xún)却?,這意味著(zhù)斷開(kāi)電源之后其內容仍然保持下來(lái)。
兩種最常見(jiàn)的 flash 設備類(lèi)型為:NOR 和 NAND?;?NOR 的 flash 技術(shù)比較早,它支持較高的讀性能,但以降低容量為代價(jià)。NAND flash 提供更大容量的同時(shí)實(shí)現快速的寫(xiě)擦性能。NAND 還需要更復雜的輸入/輸出(I/O)接口。
Flash 部件通常分為多個(gè)分區,允許同時(shí)進(jìn)行多個(gè)操作(擦除某個(gè)分區的同時(shí)讀取另一個(gè)分區)。分區再劃分為塊(通常大小為 64KB 或 128KB)。使用分區的固件可以進(jìn)一步對塊進(jìn)行獨特的分段 — 例如,一個(gè)塊中有 512 字節的分段,但不包括元數據。
Flash 設備有一個(gè)常見(jiàn)的限制,即與其他存儲設備(如 RAM 磁盤(pán))相比,它需要進(jìn)行設備管理。flash 內存設備中惟一允許的 Write 操作是將 1 修改為 0。如果需要撤銷(xiāo)操作,那么必須擦除整個(gè)塊(將所有數據重置回狀態(tài) 1)。這意味著(zhù)必須刪除該塊中的其他有效數據來(lái)實(shí)現持久化。NOR flash 內存通常一次可以編寫(xiě)一個(gè)字節,而 NAND flash 內存必須編寫(xiě)多個(gè)字節(通常為 512 字節)。
這兩種內存類(lèi)型在擦除塊方面有所不同。每種類(lèi)型都需要一個(gè)特殊的 Erase 操作,該操作可以涵蓋 flash 內存中的一個(gè)整塊。NOR 技術(shù)需要通過(guò)一個(gè)準備步驟將所有值清零,然后再開(kāi)始 Erase 操作。Erase 是針對 flash 設備的特殊操作,非常耗費時(shí)間。擦除操作與電有關(guān),它將整個(gè)塊的所有單元中的電子放掉。
NOR flash 設備通常需要花費幾秒時(shí)間來(lái)執行 Erase 操作,而 NAND 設備只需要幾毫秒。flash 設備的一個(gè)關(guān)鍵特性是可執行的 Erase 操作的數量。在 NOR 設備中,flash 內存中的每個(gè)塊可被擦除 100,000 次,而在 NAND flash 內存中可達到一百萬(wàn)次。
Flash 內存面臨的挑戰
除了前面提到的一些限制以外,管理 flash 設備還面臨很多挑戰。三個(gè)最重大的挑戰分別是垃圾收集、管理壞塊和平均讀寫(xiě)。
垃圾收集
垃圾收集 是一個(gè)回收無(wú)效塊的過(guò)程(無(wú)效塊中包含了一些無(wú)效數據)?;厥者^(guò)程包括將有效數據移動(dòng)到新塊,然后擦除無(wú)效塊從而使它變?yōu)榭捎?。如果文件系統的可用空間較少,那么通常將在后臺執行這一過(guò)程(或者根據需要執行)。
管理壞塊
用的時(shí)間長(cháng)了,flash 設備就會(huì )出現壞塊,甚至在出廠(chǎng)時(shí)就會(huì )因出現壞塊而不能使用。如果 flash 操作(例如 Erase)失敗,或者 Write 操作無(wú)效(通過(guò)無(wú)效的錯誤校正代碼發(fā)現,Error Correction Code,ECC),那么說(shuō)明出現了壞塊。
識別出壞塊后,將在 flash 內部將這些壞塊標記到一個(gè)壞塊表中。具體操作取決于設備,但是可以通過(guò)一組獨立的預留塊來(lái)(不同于普通數據塊管理)實(shí)現。對壞塊進(jìn)行處理的過(guò)程 — 不管是出廠(chǎng)時(shí)就有還是在使用過(guò)程中出現 — 稱(chēng)為壞塊管理。在某些情況下,可以通過(guò)一個(gè)內部微控制器在硬件中實(shí)現,因此對于上層文件系統是透明的。
前面提到 flash 設備屬于耗損品:在變成壞塊以前,可以執行有限次數的反復的 Erase 操作(因此必須由壞塊管理進(jìn)行標記)。平均讀寫(xiě)算法能夠最大化 flash 的壽命。平均讀寫(xiě)有兩種形式:動(dòng)態(tài)平均讀寫(xiě) 和靜態(tài)平均讀寫(xiě) 。
動(dòng)態(tài)平均讀寫(xiě)解決了塊的 Erase 周期的次數限制。動(dòng)態(tài)平均讀寫(xiě)算法并不是隨機使用可用的塊,而是平均使用塊,因此,每個(gè)塊都獲得了相同的使用機會(huì )。靜態(tài)平均讀寫(xiě)算法解決了一個(gè)更有趣的問(wèn)題。除了最大化 Erase 周期的次數外,某些 flash 設備在兩個(gè) Erase 周期之間還受到最大化 Read 周期的影響。這意味著(zhù)如果數據在塊中存儲的時(shí)間太長(cháng)并且被讀了很多次,數據會(huì )逐漸消耗直至丟失。靜態(tài)平均讀寫(xiě)算法解決了這一問(wèn)題,因為它可以定期將數據移動(dòng)到新塊。
系統架構
到目前為止,我已經(jīng)討論了 flash 設備及其面臨的基本挑戰?,F在,讓我們看看這些設備如何組合成為一個(gè)分層架構的一部分(參加圖 1)。架構的頂層是虛擬文件系統(VFS),它為高級應用程序提供通用接口。VFS 下面是 flash 文件系統(將在下節介紹)。接下來(lái)是 Flash 轉換層(Flash Translation Layer,FTL),它整體管理 flash 設備,包括從底層 flash 設備分配塊、地址轉換、動(dòng)態(tài)平均讀寫(xiě)和垃圾收集。在某些 flash 設備中,可以在硬件中實(shí)現一部分 FTL 。
圖 1. flash 系統的基本架構
Linux 內核使用內存技術(shù)設備(Memory Technology Device,MTD)接口,這是針對 flash 系統的通用接口。MTD 可以自動(dòng)檢測 flash 設備總線(xiàn)的寬度以及實(shí)現總線(xiàn)寬度所需設備的數量。
Flash 文件系統
Linux 可以使用多種 flash 文件系統。下一小節將解釋每種文件系統的設計和優(yōu)點(diǎn)。
Journaling Flash File System
Journaling Flash File System 是針對 Linux 的最早 flash 文件系統之一。 JFFS 是一種專(zhuān)門(mén)為 NOR flash 設備設計的日志結構文件系統。它非常獨特,能夠解決許多 flash 設備問(wèn)題,但同時(shí)也導致一些新問(wèn)題。
JFFS 將 flash 設備視為一種循環(huán)的塊日志。寫(xiě)入 flash 的數據被寫(xiě)到了空間的末尾,開(kāi)始部分的塊則被收回,而兩者之間的空間是空閑的;當空間變少時(shí),將執行垃圾收集。垃圾收集器將有效塊移動(dòng)到日志的尾部,跳過(guò)無(wú)效或廢棄塊,并擦除它們(參見(jiàn)圖 2)。因此這種文件系統可以自動(dòng)實(shí)現靜態(tài)和動(dòng)態(tài)平均讀寫(xiě)。這種架構的主要缺點(diǎn)是過(guò)于頻繁地執行擦除操作(而沒(méi)有使用最佳擦除策略),從而使設備迅速磨損。
圖 2. 在垃圾收集之前和之后循環(huán)日志
掛載 JFFS 時(shí)結構細節將讀取到內存中,這將延緩掛載時(shí)間并消耗更多的內存。
Journaling Flash File System 2
盡管 JFFS 在早期非常有用,但是它的平均讀寫(xiě)算法容易縮短 NOR flash 設備的壽命。因此重新設計了底層算法,去掉了循環(huán)日志。JFFS2 算法專(zhuān)門(mén)為 NAND flash 設備設計,并且改善壓縮性能。
在 JFFS2 中,flash 中的每個(gè)塊都是單獨處理的。JFFS2 通過(guò)維護塊列表來(lái)充分地對設備執行平均讀寫(xiě)。clean 列表表示設備中的塊全部為有效節點(diǎn)。dirty 列表中的塊至少包含有一個(gè)廢棄節點(diǎn)。最后,free 列表包含曾經(jīng)執行過(guò)擦除操作并且可以使用的塊。
垃圾收集算法通過(guò)合理的方法智能地判斷應該回收的塊。目前,這個(gè)算法根據概率從 clean 或 dirty 列表中選擇。dirty 列表的選擇概率為 99%(將有效內容移到另一個(gè)塊),而 clean 列表的選擇概率為 1%(將內容移到新的塊)。在這兩種情況中,對選擇的塊執行擦除操作,然后將其置于 free 列表(參見(jiàn)圖 3)。這允許垃圾收集器重用廢棄的塊,但是仍然圍繞 flash 移動(dòng)數據,以支持靜態(tài)平均讀寫(xiě)。
圖 3. JFFS2 中的塊管理和垃圾收集
Yet Another Flash File System
YAFFS 是針對 NAND flash 開(kāi)發(fā)的另一種 flash 文件系統。最早的版本(YAFFS)支持 512 字節頁(yè)面的 flash 設備,但是較新的版本(YAFFS2)支持頁(yè)面更大的新設備以及更大的 Write 限制。
大多數 flash 文件系統會(huì )對廢棄塊進(jìn)行標記,但是 YAFFS2 使用單調遞增數字序列號額外地標記塊。在掛載期間掃描文件系統時(shí),可以快速標識有效的 inode。YAFFS 保留在 RAM 中的樹(shù)以表示 flash 設備的塊結構,包括通過(guò)檢查點(diǎn)(checkpointing)實(shí)現快速掛載 — 這個(gè)過(guò)程將在正常卸載時(shí)將 RAM 樹(shù)結構保存到 flash 設備,以在掛載時(shí)快速讀取和恢復到 RAM(參見(jiàn)圖 4)。與其他 flash 文件系統相比,YAFFS2 的掛載時(shí)性能是它的最大優(yōu)勢。
圖 4. YAFFS2 中的塊管理和垃圾收集
只讀式壓縮文件系統
在某些嵌入式系統中,沒(méi)有必要提供可更改的文件系統:一個(gè)不可更改(immutable)的文件系統已經(jīng)足夠。Linux 支持多種只讀文件系統,最有用的兩種是 cramfs 和 SquashFS。
Cramfs
cramfs 文件系統是一種可用于 flash 設備的壓縮式 Linux 只讀文件系統。cramfs 的主要特點(diǎn)是簡(jiǎn)單和較高的空間利用率。這種文件系統用于內存占用較小的嵌入式設計。
雖然 cramfs 元數據沒(méi)有經(jīng)過(guò)壓縮,但是 cramfs 針對每個(gè)頁(yè)面使用 zlib 壓縮,從而允許隨機的頁(yè)面訪(fǎng)問(wèn)(訪(fǎng)問(wèn)時(shí)對頁(yè)面進(jìn)行解壓縮)。
您可以通過(guò) mkcramfs 實(shí)用工具和 loopback 設備嘗試使用 cramfs。
SquashFS
SquashFS 是另一種可用于 flash 設備的壓縮式 Linux 只讀文件系統。您可以在很多 Live CD Linux 發(fā)行版中找到 SquashFS。除了支持 zlib 壓縮外,SquashFS 還使用 Lembel-Ziv-Markov chain Algorithm (LZMA) 改善壓縮并提高速度。
和 cramfs 一樣,您可以通過(guò) mksquashfs 和 loopback 設備在標準 Linux 系統上使用 SquashFS。
結束語(yǔ)
和大多數開(kāi)放源碼一樣,軟件在不斷演變,并且新的 flash 文件系統正在開(kāi)發(fā)之中。一種還處于開(kāi)發(fā)階段的有趣的備選文件系統是 LogFS,它包含了一些非常新穎的想法。例如,LogFS 在 flash 設備中保持了一個(gè)樹(shù)結構,因此掛載時(shí)間和傳統的文件系統差不多(比如 ext2)。它還使用一種復雜的樹(shù)實(shí)現垃圾收集(一種 B+樹(shù)形式)。然而,LogFS 最有趣的地方是它具有出色的可伸縮性并且支持大型 flash 部件。
隨著(zhù) flash 文件系統的日益流行,您將看到針對它們的大量研究。LogFS 就是一個(gè)例子,但是其他類(lèi)似于 UbiFS 的文件系統也在不斷發(fā)展。Flash 文件系統的架構非常有趣,并在還將是未來(lái)技術(shù)創(chuàng )新的源泉。
評論