<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # JFFS2文件系統簡介 JFFS2 是一個日志結構(log-structured)的文件系統, 包含數據 和 原數據(meta-data)的節點在閃存上順序的存儲。 JFFS2 之所以選擇日志結構的存儲方式,是因為對閃存的更新應該是 out-of-place 的更新方式,而不是對磁盤的 in-place 的更新方式。在閃存上 in-place 更新方式的問題我們已經在閃存轉換層一節描述過了。 2.1 節點頭部定義和兼容性 JFFS2 將文件系統的數據和原數據以節點的形式存儲在閃存上,具體來說節點頭部的定義如下: 圖二 圖二 幻數屏蔽位:0x1985 用來標識 JFFS2 文件系統。 節點類型:JFFS2 自身定義了三種節點類型,但是考慮到文件系統可擴展性和兼容性,JFFS2從 ext2 借鑒了經驗,節點類型的最高兩位被用來定義節點的兼容屬性,具體來說有下面幾種兼容屬性: JFFS2_FEATURE_INCOMPAT:當 JFFS2 發現了一個不能識別的節點類型,并且它的兼容屬性是 JFFS2_FEATURE_INCOMPAT,那么 JFFS2 必須拒絕掛載(mount)文件系統。 JFFS2_FEATURE_ROCOMPAT:當 JFFS2 發現了一個不能識別的節點類型,并且它的兼容屬性是 JFFS2_FEATURE_ROCOMPAT,那么 JFFS2 必須以只讀的方式掛載文件系統。 JFFS2_FEATURE_RWCOMPAT_DELETE:當 JFFS2 發現了一個不能識別的節點類型,并且它的兼容屬性是 JFFS2_FEATURE_RWCOMPAT_DELETE,那么在垃圾回收的時候,這個節點可以被刪除。 JFFS2_FEATURE_RWCOMPAT_COPY:當 JFFS2 發現了一個不能識別的節點類型,并且它的兼容屬性是 JFFS2_FEATURE_RWCOMPAT_COPY,那么在垃圾回收的時候,這個節點要被拷貝到新的位置。 節點總長度:包括節點頭和數據的長度。 節點頭部 CRC 校驗:包含節點頭部的校驗碼,為文件系統的可靠性提供了支持。 2.2 節點類型 JFFS2 定義了三種節點類型: JFFS2_NODETYPE_INODE: INODE 節點包含了i-節點的原數據(i節點號,文件的組 ID, 屬主 id, 訪問時間,偏移,長度等),文件數據被附在 INODE 節點之后。除此之外,每個 INODE 節點還有一個版本號,它被用來維護屬于一個i-節點的所有 INODE 節點的全序關系。下面舉例來說明這個全序關系在 JFFS2 的使用: 圖三 圖三 因此,當文件系統從閃存上讀節點信息后,會生成下面的映射信息: 圖四 圖四 根據這個映射信息表,文件系統就知道到相應的 INODE 節點去讀取相應的文件內容。最后要說明的是,JFFS2 支持文件數據的壓縮存儲,因此在 INODE 節點中還包含了所使用的壓縮算法,在讀取數據的時候選擇相應的壓縮算法來解壓縮。 JFFS2_NODETYPE_DIRENT:DIRENT 節點就是把文件名與 i 節點對應起來。在 DIRENT節點中也有一個版本號,這個版本號的作用主要是用來刪除一個 dentry。具體來說,當我們要從一個目錄中刪除一個 dentry 時,我們要寫一個 DIRENT 節點,節點中的文件名與被刪除的 dentry 中的文件名相同,i 節點號置為 0,同時設置一個更高的版本號。 JFFS2_NODETYPE_CLEANMARKER:當一個擦寫塊被擦寫完畢后,CLEANMARKER 節點會被寫在 NOR flash 的開頭,或 NAND flash 的 OOB(Out-Of-Band) 區域來表明這是一個干凈,可寫的擦寫塊。在 JFFS v1 中,如果掃描到開頭的 1K 都是 0xFF 就認為這個擦寫塊是干凈的。但是在實際的測試中發現,如果在擦寫的過程中突然掉電,擦寫塊上也可能會有大塊連續 0xFF,但是這并不表明這個擦寫塊是干凈的。于是我們需要 CLEANMARKER 節點來確切的標識一個干凈的擦寫塊。 2.3 JFFS2節點,擦寫塊在內存中的表示和操作 JFFS2 維護了幾個鏈表來管理擦寫塊,根據擦寫塊上的內容,一個擦寫塊會在不同的鏈表上。具體來說,當一個擦寫塊上都是合法(valid)的節點時,它會在 clean_list 上;當一個擦寫塊包含至少一個過時(obsolete)的節點時,它會在 dirty_list 上;當一個擦寫塊被擦寫完畢,并被寫入 CLEANMARKER 節點后,它會在 free_list 上。 通常情況下,JFFS2 順序的在擦寫塊上寫入不同的節點,直到一個擦寫塊被寫滿。此時 JFFS2 從 free_list 上取下一個擦寫塊,繼續從擦寫塊的開頭開始寫入節點。當 free_list 上擦寫塊的數量逐漸減少到一個預先設定的閥值的時候,垃圾回收就被觸發了,為文件系統清理出更多的可用擦寫塊。為了減少對內存的占用,JFFS2 并沒有把 i 節點所有的信息都保留在內存中,而只是把那些在請求到來時不能很快獲得的信息保留在內存中。具體來說,對于在閃存上的每個 i 節點,在內存里都有一個 struct jffs2_inode_cache 與之對應,這個結構里保存了 i 節點號,指向 i 節點的連接數,以及一個指向屬于這個 i 節點的物理節點鏈表的指針。所有的 struct jffs2_inode_cache 存儲在一個哈希表中。閃存上的每個節點在內存中由一個 struct jffs2_raw_node_ref 表示,這個結構里保存了此節點的物理偏移,總長度,以及兩個指向 struct jffs2_raw_node_ref 的指針。一個指針指向此節點在物理擦寫塊上的下一個節點,另一個指針指向屬于同一個 i-節點的物理節點鏈表的下一個節點。 圖五 圖五 在閃存上的節點的起始偏移都是 4 字節對齊的,所以 struct jffs2_inode_cache 中flash_offset 的最低兩位沒有被用到。JFFS2 正好利用最低位作為此節點是否過時的標記。 下面舉一例來說明 JFFS2 是如何使用這些數據結構的。VFS 調用 iget() 來得到一個 i 節點的信息,當這個 i 節點不在緩存中的時候,VFS 就會調用 JFFS2 的 read_inode() 回調函數來得到 i 節點信息。傳給 read_inode() 的參數是 i 節點號,JFFS2 用這個 i 節點號從哈希表中查找相應的 struct jffs2_inode_cache,然后利用屬于這個 i 節點的節點鏈表從閃存上讀入節點信息,建立類似于表三的映射信息。 2.4 JFFS2 掛載過程 JFFS2 的掛載過程分為四個階段: 1) JFFS2 掃描閃存介質,檢查每個節點 CRC 校驗碼的合法性,同時分配了 struct jffs2_inode_cache 和 struct jffs2_raw_node_ref 2) 掃描每個 i 節點的物理節點鏈表,標識出過時的物理節點;對每一個合法的 dentry 節點,將相應的 jffs2_inode_cache 中的 nlink 加一。 3 找出 nlink 為 0 的 jffs2_inode_cache,釋放相應的節點。 4 釋放在掃描過程中使用的臨時信息。 2.5 JFFS2 垃圾回收機制 當 free_list 上的擦寫塊數太少了,垃圾回收就會被觸發。垃圾回收主要的任務就是回收那些已經過時的節點,但是除此之外它還要考慮磨損平衡的問題。因為如果一味的從 dirty_list上選取擦寫塊進行垃圾回收,那么 dirty_list 上的擦寫塊將先于 clean_list 上的擦寫塊被磨損壞。JFFS2 的處理方式是以 99% 的概率從 dirty_list,1% 的概率從 clean_list 上取一個擦寫塊下來。由此可以看出 JFFS2 的設計思想是偏向于性能,同時兼顧磨損平衡。對這個塊上每一個沒有過時的節點執行相同的操作: 1 找出這個節點所屬的 i 節點號(見圖五)。 2 調用 iget(),建立這個 i 節點的文件映射表。 3 找出這個節點上沒有過時的數據內容,并且如果合法的數據太少,JFFS2 還會合并相鄰的節點。 4 將數據讀入倒緩存里,然后將它拷貝到新的擦寫塊上。 5 將回收的節點置為過時。 當擦寫塊上所有的節點都被置為過時,就可以擦寫這個擦寫塊,回收使用它。 回頁首 3. JFFS2 的不足之處 3.1 掛載時間過長 JFFS2 的掛載過程需要對閃存從頭到尾的掃描,這個過程是很慢的,我們在測試中發現,掛載一個 16M 的閃存有時需要半分鐘以上的時間。 3.2 磨損平衡的隨意性(random nature) JFFS2 對磨損平衡是用概率的方法來解決的,這很難保證磨損平衡的確定性。在某些情況下,可能造成對擦寫塊不必要的擦寫操作;在某些情況下,又會引起對磨損平衡調整的不及時。 3.3 很差的擴展性 JFFS2 中有兩個地方的處理是 O(N) 的,這使得它的擴展性很差。 首先,掛載時間同閃存的大小,閃存上節點數目成正比。 其次,雖然 JFFS2 盡可能的減少內存的占用,但通過上面對 JFFS2 的介紹我們可以知道實際上它對內存的占用量是同 i 節點數和閃存上的節點數成正比的。 因此在實際應用中,JFFS2 最大能用在 128M 的閃存上。 回頁首 4. JFFS2 的新特性 最近加入到 JFFS2 中的兩個補丁程序分別解決了上面提到的掛載時間過長和磨損平衡隨意性的問題。 4.1 磨損塊小結補丁程序(erase block summary patch) 這個補丁程序最基本的思想就是用空間來換時間。具體來說,就是將每個擦寫塊每個節點的原數據信息寫在這個擦寫塊的最后,當 JFFS2 掛載的時候,對每個擦寫塊只需要讀一次來讀取這個小結節點,因此大大減少了掛載時間。使用了磨損塊小結補丁程序,一個擦寫塊的結構就像下面這樣: 圖六 圖六 根據我們的測試,使用磨損塊小結補丁程序,掛載一個 12M 的閃存需要 2~3 秒,掛載一個 16M 的閃存需要 3~4 秒。 4.2 改進的磨損平衡補丁程序 這個補丁程序的基本思想是,記錄每個擦寫塊的擦寫次數,當閃存上各個擦寫塊的擦寫次數的差距超過某個預定的閥值,開始進行磨損平衡的調整。調整的策略是,在垃圾回收時將擦寫次數小的擦寫塊上的數據遷移到擦寫次數大的擦寫塊上。這樣一來我們提高了磨損平衡的確定性,我們可以知道什么時候開始磨損平衡的調整,也可以知道選取哪些擦寫塊進行磨損平衡的調整。 4.3 擦寫塊頭部補丁程序 在寫改進的磨損平衡補丁程序的過程之中,我們需要記錄每個擦寫塊的擦寫次數,這個信息需要記錄在各自的擦寫塊上。可是我們發現 JFFS2 中缺少一種靈活的對每個擦寫塊的信息進行擴展的機制。于是我們為每個擦寫塊引入了擦寫塊頭部(header),這個頭部負責紀錄每個擦寫塊的信息(比如說擦寫次數),并且它提供了靈活的擴展機制,將來如果有新的信息需要記錄,可以很容易的加入到頭部之中。 回頁首 5. JFFS3 簡介 雖然不斷有新的補丁程序來提高 JFFS2 的性能,但是不可擴展性是它最大的問題,但是這是它自身設計的先天缺陷,是沒有辦法靠后天來彌補的。因此我們需要一個全新的文件系統,而 JFFS3 就是這樣的一個文件系統,JFFS3 的設計目標是支持大容量閃存(>1TB)的文件系統。JFFS3 與 JFFS2 在設計上根本的區別在于,JFFS3 將索引信息存放在閃存上,而 JFFS2將索引信息保存在內存中。比如說,由給定的文件內的偏移定位到存儲介質上的物理偏移地址所需的信息,查找某個目錄下所有的目錄項所需的信息都是索引信息的一種。 JFFS3 現在還處于設計階段,文件系統的基本結構借鑒了 Reiser4 的設計思想,整個文件系統就是一個 B+ 樹。JFFS3 的發起者正工作于垃圾回收機制的設計,這是 JFFS3 中最復雜,也是最富有挑戰性的部分。JFFS3 的設計文檔可以在http://www.linux-mtd.infradead.org/doc/jffs3.html 得到,有興趣的讀者可以積極參與到 JFFS3 的設計中,發表自己的見解,參與討論。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看