|
|
硬盤 FAT 文件系統原理的詳細分析 |
|
一、硬盤的物理結構:
硬盤存儲數據是根據電、磁轉換原理實現的。硬盤由一個或幾個表面鍍有磁性物質的金屬或玻璃等物質盤片以及盤片兩面所安裝的磁頭和相應的控制電路組成 ( 圖 1) ,其中盤片和磁頭密封在無塵的金屬殼中。 硬盤工作時,盤片以設計轉速高速旋轉,設置在盤片表面的磁頭則在電路控制下徑向移動到指定位置然後將數據存儲或讀取出來。當系統向硬盤寫入數據時,磁頭中 『 寫數據 』 電流產生磁場使盤片表面磁性物質狀態發生改變,並在寫電流磁場消失後仍能保持,這樣數據就存儲下來了;當系統從硬盤中讀數據時,磁頭經過盤片指定區域,盤片表面磁場使磁頭產生感應電流或線圈阻抗產生變化,經相關電路處理後還原成數據。因此只要能將盤片表面處理得更平滑、磁頭設計得更精密以及盡量提高盤片旋轉速度,就能造出容量更大、讀寫數據速度更快的硬盤。這是因為盤片表面處理越平、轉速越快就能越使磁頭離盤片表面越近,提高讀、寫靈敏度和速度;磁頭設計越小越精密就能使磁頭在盤片上佔用空間越小,使磁頭在一張盤片上建立更多的磁道以存儲更多的數據。 二、硬盤的邏輯結構: 硬盤由很多盤片 (platter) 組成,每個盤片的每個面都有一個讀寫磁頭。如果有 N 個盤片。就有 2N 個面,對應 2N 個磁頭 (Heads) ,從 0 、 1 、 2 開始編號。每個盤片被劃分成若乾個同心圓磁道 ( 邏輯上的,是不可見的。 ) 每個盤片的劃分規則通常是一樣的。這樣每個盤片的半徑均為固定值 R 的同心圓再邏輯上形成了一個以電機主軸為軸的柱面 (Cylinders) ,從外至裡編號為 0 、 1 、 2…… 每個盤片上的每個磁道又被劃分為幾十個扇區 (Sector) ,通常的容量是 512byte ,並按照一定規則編號為 1 、 2 、 3…… 形成 Cylinders×Heads×Sector 個扇區。這三個參數即是硬盤的物理參數。我們下面的很多實踐需要深刻理解這三個參數的意義。 三、磁盤引導原理: 3.1 MBR(master boot record) 扇區: 計算機在按下 power 鍵以後,開始執行主板 bios 程序。進行完一系列檢測和配置以後。開始按 bios 中設定的系統引導順序引導系統。假定現在是硬盤。 Bios 執行完自己的程序後如何把執行權交給硬盤呢。交給硬盤後又執行存儲在哪裡的程序呢。其實,稱為 mbr 的一段代碼起著舉足輕重的作用。 MBR(master boot record), 即主引導記錄,有時也稱主引導扇區。位於整個硬盤的 0 柱面 0 磁頭 1 扇區 ( 可以看作是硬盤的第一個扇區 ) , bios 在執行自己固有的程序以後就會 jump 到 mbr 中的第一條指令。將系統的控制權交由 mbr 來執行。在總共 512byte 的主引導記錄中, MBR 的引導程序佔了其中的前 446 個字節 ( 偏移 0H~ 偏移 1BDH) ,隨後的 64 個字節 ( 偏移 1BEH~ 偏移 1FDH) 為 DPT(Disk PartitionTable ,硬盤分區表 ) ,最後的兩個字節 『55 AA』( 偏移 1FEH~ 偏移 1FFH) 是分區有效結束標志。 MBR 不隨操作系統的不同而不同,意即不同的操作系統可能會存在相同的 MBR ,即使不同, MBR 也不會夾帶操作系統的性質。具有公共引導的特性。 我們來分析一段 mbr 。下面是用 winhex 查看的一塊希捷 120GB 硬盤的 mbr 。
你的硬盤的 MBR 引導代碼可能並非這樣。不過即使不同,所執行的功能大體是一樣的。 這裡找 wowocock 關於磁盤 mbr 的反編譯 ,已加了詳細的注釋,感興趣可以細細研究一下。 我們看 DPT 部分。操作系統為了便於用戶對磁盤的管理。加入了磁盤分區的概念。即將一塊磁盤邏輯劃分為幾塊。磁盤分區數目的多少只受限於 C ~ Z 的英文字母的數目,在上圖 DPT 共 64 個字節中如何表示多個分區的屬性呢 ?microsoft 通過鏈接的方法解決了這個問題。在 DPT 共 64 個字節中,以 16 個字節為分區表項單位描述一個分區的屬性。也就是說,第一個分區表項描述一個分區的屬性,一般為基本分區。第二個分區表項描述除基本分區外的其餘空間,一般而言,就是我們所說的擴展分區。這部分的大體說明見表 1 。
也可以在 winhex 中看到這些參數的意義:
說明: 每個分區表項佔用 16 個字節,假定偏移地址從 0 開始。如圖 3 的分區表項 3 。分區表項 4 同分區表項 3 。 1 、 0H 偏移為活動分區是否標志,只能選 00H 和 80H 。 80H 為活動, 00H 為非活動。其餘值對 microsoft 而言為非法值。 2 、重新說明一下 ( 這個非常重要 ) :大於 1 個字節的數被以低字節在前的存儲格式格式 (little endian format) 或稱反字節順序保存下來。低字節在前的格式是一種保存數的方法,這樣,最低位的字節最先出現在十六進制數符號中。例如,相對扇區數字段的值 0x3F000000 的低字節在前表示為 0x0000003F 。這個低字節在前的格式數的十進制數為 63 。 3 、系統在分區時,各分區都不允許跨柱面,即均以柱面為單位,這就是通常所說的分區粒度。有時候我們分區是輸入分區的大小為 7000M ,分出來卻是 6997M ,就是這個原因。 偏移 2H 和偏移 6H 的扇區和柱面參數中 , 扇區佔 6 位 (bit) ,柱面佔 10 位 (bit) ,以偏移 6H 為例,其低 6 位用作扇區數的二進制表示。其高兩位做柱面數 10 位中的高兩位,偏移 7H 組成的 8 位做柱面數 10 位中的低 8 位。由此可知,實際上用這種方式表示的分區容量是有限的,柱面和磁頭從 0 開始編號 , 扇區從 1 開始編號 , 所以最多只能表示 1024 個柱面 ×63 個扇區 ×256 個磁頭 ×512byte=8455716864byte 。即通常的 8.4GB( 實際上應該是 7.8GB 左右 ) 限制。實際上磁頭數通常只用到 255 個 ( 由匯編語言的尋址寄存器決定 ), 即使把這 3 個字節按線性尋址,依然力不從心。 在後來的操作系統中,超過 8.4GB 的分區其實已經不通過 C/H/S 的方式尋址了。而是通過偏移 CH ~偏移 FH 共 4 個字節 32 位線性扇區地址來表示分區所佔用的扇區總數。可知通過 4 個字節可以表示 2^32 個扇區,即 2TB=2048GB ,目前對於大多數計算機而言,這已經是個天文數字了。在未超過 8.4GB 的分區上, C/H/S 的表示方法和線性扇區的表示方法所表示的分區大小是一致的。也就是說,兩種表示方法是協調的。即使不協調,也以線性尋址為准。 ( 可能在某些系統中會提示出錯 ) 。超過 8.4GB 的分區結束 C/H/S 一般填充為 FEH FFH FFH 。即 C/H/S 所能表示的最大值。有時候也會用柱面對 1024 的模來填充。不過這幾個字節是什麼其實都無關緊要了。 雖然現在的系統均采用線性尋址的方式來處理分區的大小。但不可跨柱面的原則依然沒變。本分區的扇區總數加上與前一分區之間的保留扇區數目依然必須是柱面容量的整數倍。 ( 保留扇區中的第一個扇區就是存放分區表的 MBR 或虛擬 MBR 的扇區,分區的扇區總數在線性表示方式上是不計入保留扇區的。如果是第一個分區,保留扇區是本分區前的所有扇區。 附:分區表類型標志如圖 4
3.2 擴展分區 擴展分區中的每個邏輯驅動器都存在一個類似於 MBR 的擴展引導記錄 ( Extended Boot Record, EBR) ,也有人稱之為虛擬 mbr 或擴展 mbr ,意思是一樣的。擴展引導記錄包括一個擴展分區表和該扇區的標簽。擴展引導記錄將記錄只包含擴展分區中每個邏輯驅動器的第一個柱面的第一面的信息。一個邏輯驅動器中的引導扇區一般位於相對扇區 32 或 63 。但是,如果磁盤上沒有擴展分區,那麼就不會有擴展引導記錄和邏輯驅動器。第一個邏輯驅動器的擴展分區表中的第一項指向它自身的引導扇區。第二項指向下一個邏輯驅動器的 EBR 。如果不存在進一步的邏輯驅動器,第二項就不會使用,而且被記錄成一系列零。如果有附加的邏輯驅動器,那麼第二個邏輯驅動器的擴展分區表的第一項會指向它本身的引導扇區。第二個邏輯驅動器的擴展分區表的第二項指向下一個邏輯驅動器的 EBR 。擴展分區表的第三項和第四項永遠都不會被使用。 通過一幅 4 分區的磁盤結構圖可以看到磁盤的大致組織形式。如圖 5 :
關於擴展分區,如圖 6 所示,擴展分區中邏輯驅動器的擴展引導記錄是一個連接表。該圖顯示了一個擴展分區上的三個邏輯驅動器,說明了前面的邏輯驅動器和最後一個邏輯驅動器之間在擴展分區表中的差異。
除了擴展分區上最後一個邏輯驅動器外,表 2 中所描述的擴展分區表的格式在每個邏輯驅動器中都是重復的:第一個項標識了邏輯驅動器本身的引導扇區,第二個項標識了下一個邏輯驅動器的 EBR 。最後一個邏輯驅動器的擴展分區表只會列出它本身的分區項。最後一個擴展分區表的第二個項到第四個項被使用。
擴展分區表項中的相對扇區數字段所顯示的是從擴展分區開始到邏輯驅動器中第一個扇區的位移的字節數。總扇區數字段中的數是指組成該邏輯驅動器的扇區數目。總扇區數字段的值等於從擴展分區表項所定義的引導扇區到邏輯驅動器末尾的扇區數。 有時候在磁盤的末尾會有剩餘空間,剩餘空間是什麼呢?我們前面說到,分區是以 1 柱面的容量為分區粒度的,那麼如果磁盤總空間不是整數個柱面的話,不夠一個柱面的剩下的空間就是剩餘空間了,這部分空間並不參與分區,所以一般無法利用。照道理說,磁盤的物理模式決定了磁盤的總容量就應該是整數個柱面的容量,為什麼會有不夠一個柱面的空間呢。在我的理解看來,本來現在的磁盤為了更大的利用空間,一般在物理上並不是按照外圍的扇區大於裡圈的扇區這種管理方式,只是為了與操作系統兼容而抽象出來 CHS 。可能其實際空間 zymail@vip.sina.com 四、 FAT 分區原理 先來一幅結構圖:
現在我們著重研究 FAT 格式分區內數據是如何存儲的。 FAT 分區格式是 MICROSOFT 最早支持的分區格式,依據 FAT 表中每個簇鏈的所佔位數 ( 有關概念,後面會講到 ) 分為 fat12 、 fat16 、 fat32 三種格式 " 變種 " ,但其基本存儲方式是相似的。 仔細研究圖 7 中的 fat16 和 fat32 分區的組成結構。下面依次解釋 DBR 、 FAT1 、 FAT2 、根目錄、數據區、剩餘扇區的概念。提到的地址如無特別提示均為分區內部偏移。 4.1 關於 DBR. DBR 區 (DOS BOOT RECORD) 即操作系統引導記錄區的意思,通常佔用分區的第 0 扇區共 512 個字節 ( 特殊情況也要佔用其它保留扇區,我們先說第 0 扇 ) 。在這 512 個字節中,其實又是由跳轉指令,廠商標志和操作系統版本號, BPB(BIOS Parameter Block) ,擴展 BPB , os 引導程序,結束標志幾部分組成。 以用的最多的 FAT32 為例說明分區 DBR 各字節的含義。見圖 8 。
圖 8 的對應解釋見表 3
圖 9 給出了 winhex 對圖 8 DBR 的相關參數解釋:
根據上邊圖例,我們來討論 DBR 各字節的參數意義。 MBR 將 CPU 執行轉移給引導扇區,因此,引導扇區的前三個字節必須是合法的可執行的基於 x86 的 CPU 指令。這通常是一條跳轉指令,該指令負責跳過接下來的幾個不可執行的字節 (BPB 和擴展 BPB) ,跳到操作系統引導代碼部分。 跳轉指令之後是 8 字節長的 OEM ID ,它是一個字符串, OEM ID 標識了格式化該分區的操作系統的名稱和版本號。為了保留與 MS-DOS 的兼容性,通常 Windows 2000 格式化該盤是在 FAT16 和 FAT32 磁盤上的該字段中記錄了 『MSDOS 5.0』 ,在 NTFS 磁盤上 ( 關於 ntfs ,另述 ) , Windows 2000 記錄的是 『NTFS』 。通常在被 Windows 95 格式化的磁盤上 OEM ID 字段出現 『MSWIN4.0』 ,在被 Windows 95 OSR2 和 Windows 98 格式化的磁盤上 OEM ID 字段出現 『MSWIN4.1』 。 接下來的從偏移 0x0B 開始的是一段描述能夠使可執行引導代碼找到相關參數的信息。通常稱之為 BPB(BIOS Parameter Block) , BPB 一般開始於相同的位移量,因此,標准的參數都處於一個已知的位置。磁盤容量和幾何結構變量都被封在 BPB 之中。由於引導扇區的第一部分是一個 x86 跳轉指令。因此,將來通過在 BPB 末端附加新的信息,可以對 BPB 進行擴展。只需要對該跳轉指令作一個小的調整就可以適應 BPB 的變化。圖 9 已經列出了項目的名稱和取值,為了系統的研究,針對圖 8 ,將 FAT32 分區格式的 BPB 含義和擴展 BPB 含義釋義為表格,見表 4 和表 5 。
DBR 的偏移 0x5A 開始的數據為操作系統引導代碼。這是由偏移 0x00 開始的跳轉指令所指向的。在圖 8 所列出的偏移 0x00~0x02 的跳轉指令 "EB 58 90" 清楚地指明了 OS 引導代碼的偏移位置。 jump 58H 加上跳轉指令所需的位移量,即開始於 0x5A 。此段指令在不同的操作系統上和不同的引導方式上,其內容也是不同的。大多數的資料上都說 win98, 構建於 fat 基本分區上的 win2000,winxp 所使用的 DBR 只佔用基本分區的第 0 扇區。他們提到,對於 fat32 ,一般的 32 個基本分區保留扇區只有第 0 扇區是有用的。實際上,以 FAT32 構建的操作系統如果是 win98, 系統會使用基本分區的第 0 扇區和第 2 扇區存儲 os 引導代碼;以 FAT32 構建的操作系統如果是 win2000 或 winxp, 系統會使用基本分區的第 0 扇區和第 0xC 扇區 (win2000 或 winxp, 其第 0xC 的位置由第 0 扇區的 0xAB 偏移指出 ) 存儲 os 引導代碼。所以,在 fat32 分區格式上,如果 DBR 一扇區的內容正確而缺少第 2 扇區 (win98 系統 ) 或第 0xC 扇區 (win2000 或 winxp 系統 ) ,系統也是無法啟動的。如果自己手動設置 NTLDR 雙系統,必須知道這一點。 DBR 扇區的最後兩個字節一般存儲值為 0x55AA 的 DBR 有效標志,對於其他的取值,系統將不會執行 DBR 相關指令。上面提到的其他幾個參與 os 引導的扇區也需以 0x55AA 為合法結束標志。 FAT16 DBR : FAT32 中 DBR 的含義大致如此,對於 FAT12 和 FAT16 其基本意義類似,只是相關偏移量和參數意義有小的差異, FAT 格式的區別和來因,以後會說到,此處不在多說 FAT12 與 FAT16 。我將 FAT16 的扇區參數意義列表。感興趣的朋友自己研究一下,和 FAT32 大同小異的。
4.2 關於保留扇區 在上述 FAT 文件系統 DBR 的偏移 0x0E 處,用 2 個字節存儲保留扇區的數目。所謂保留扇區 ( 有時候會叫系統扇區,隱藏扇區 ) ,是指從分區 DBR 扇區開始的僅為系統所有的扇區,包括 DBR 扇區。在 FAT16 文件系統中,保留扇區的數據通常設置為 1 ,即僅僅 DBR 扇區。而在 FAT32 中,保留扇區的數據通常取為 32 ,有時候用 Partition Magic 分過的 FAT32 分區會設置 36 個保留扇區,有的工具可能會設置 63 個保留扇區。 FAT32 中的保留扇區除了磁盤總第 0 扇區用作 DBR ,總第 2 扇區 (win98 系統 ) 或總第 0xC 扇區 (win2000,winxp) 用作 OS 引導代碼擴展部分外,其餘扇區都不參與操作系統管理與磁盤數據管理,通常情況下是沒作用的。操作系統之所以在 FAT32 中設置保留扇區,是為了對 DBR 作備份或留待以後昇級時用。 FAT32 中, DBR 偏移 0x34 佔 2 字節的數據指明了 DBR 備份扇區所在,一般為 0x06 ,即第 6 扇區。當 FAT32 分區 DBR 扇區被破壞導致分區無法訪問時。可以用第 6 扇區的原備份替換第 0 扇區來找回數據。 4.3 FAT 表和數據的存儲原則 FAT 表 (File Allocation Table 文件分配表 ) ,是 Microsoft 在 FAT 文件系統中用於磁盤數據 ( 文件 ) 索引和定位引進的一種鏈式結構。假如把磁盤比作一本書, FAT 表可以認為相當於書中的目錄,而文件就是各個章節的內容。但 FAT 表的表示方法卻與目錄有很大的不同。 在 FAT 文件系統中,文件的存儲依照 FAT 表制定的簇鏈式數據結構來進行。同時, FAT 文件系統將組織數據時使用的目錄也抽象為文件,以簡化對數據的管理。 ★ 存儲過程假想: 我們模擬對一個分區存儲數據的過程來說明 FAT 文件系統中數據的存儲原則。 假定現在有一個空的完全沒有存放數據的磁盤,大小為 100KB ,我們將其想象為線形的空間地址。為了存儲管理上的便利,我們人為的將這 100KB 的空間均分成 100 份,每份 1KB 。我們來依次存儲這樣幾個文件: A.TXT( 大小 10KB),B.TXT( 大小 53.6KB) , C.TXT( 大小 20.5KB) 。 最起碼能夠想到,我們可以順序的在這 100KB 空間中存放這 3 個文件。同時不要忘了,我們還要記下他們的大小和開始的位置,這樣下次要用時纔能找的到,這就像是目錄。為了便於查找,我們假定用第 1K 的空間來存儲他們的特征 ( 屬性 ) 。還有,我們設計的存儲單位是 1KB ,所以, A.TXT 我們需要 10 個存儲單位 ( 為了說明方便,我們把存儲單位叫做 『 簇 』 吧。也能少打點字,呵呵。 ) , B.TXT 需要 54 個簇, C.TXT 需要 21 個簇。可能有人會說 B.TXT 和 C.TXT 不是各自浪費了不到 1 簇的空間嗎?乾嘛不讓他們緊挨著,不是省地方嗎?我的回答是,如果按照這樣的方式存儲,目錄中原本只需要記下簇號,現在還需要記下簇內的偏移,這樣會增加目錄的存儲量,而且存取沒有了規則,讀取也不太方便,是得不償失的。 根據上面所說的思想,我們設計了這樣的圖 4.3.1 所示的存儲方式。
我們再考慮如何來寫這三個文件的目錄。對於每個文件而言,一定要記錄的有:文件名,開始簇,大小,創建日期、時間,修改日期、時間,文件的讀寫屬性等。這裡大小能不能用結束簇來計算呢?一定不能,因為文件的大小不一定就是整數個簇的大小,否則的話像 B.TXT 的內容就是 54KB 的內容了,少了固然不行,可多了也是不行的。那麼我們怎麼記錄呢?可以想象一下。為了管理上的方便,我們用數據庫的管理方式來管理我們的目錄。於是我把 1KB 再分成 10 份,假定開始簇號為 0 ,定義每份 100B 的各個位置的代表含義如圖 4.3.2
這樣設計的結構絕對可以對文件進行正確的讀寫了。接著讓我們設計的文件系統工作吧。先改動個文件,比如 A.TXT ,增加點內容吧!咦?增加後往哪裡放呀,雖然存儲塊的後面有很多空間,但緊隨其後 B.TXT 的數據還頂著呢?要是把 A.TXT 移到後邊太浪費處理資源,而且也不一定解決問題。這個問題看來暫時解決不了。 那我們換個操作,把 B.txt 刪了, b.txt 的空間隨之釋放。這時候空間如圖 4.3.3 ,目錄如圖 4.3.4
這個操作看來還可以,我們接著做,在存入一個文件 D.txt( 大小為 60.3KB), 總共 100 簇的空間只用了 31 簇,還有 68 簇剩餘,按說能放下。可是?往那裡放呢?沒有 61 個連續的空間了,目錄行沒辦法寫了,看來無連續塊存儲暫時也不行。 你一定能夠想到我們可以在連續空間不夠或增加文件長度的時候轉移影響我們操作的其他文件,從而騰出空間來,但我要問你,那不是成天啥也不要乾了,就是倒騰東西了嗎? 看來我們設計的文件系統有致命的漏洞,怎麼解決呢?其實可以這樣解決: 首先我們允許文件的不連續存儲。目錄中依然只記錄開始簇和文件的大小。那麼我們怎麼記錄文件佔用那些簇呢,以文件映射簇不太方便,因為文件名是不固定的。我們換個思想,可以用簇來映射文件,在整個存儲空間的前部留下幾簇來記錄數據區中數據與簇號的關系。對於上例因為總空間也不大,所以用前部的 1Kb 的空間來記錄這種對應,假設 3 個文件都存儲,空間分配如圖 4.3.5 ,同時修改一下目錄,如圖 4.3.6
第一簇用來記錄數據區中每一簇的被佔用情況,暫時稱其為文件分配表。結合文件分配表和文件目錄就可以達到完全的文件讀取了。我們想到,把文件分配表做成一個數據表,以圖 4.3.7 的形式記錄簇與數據的對應。 用圖 4.3.7 的組織方式是完全可以實現對文件佔有簇的記錄的。但還不夠效率。比如文件名在文件分配表中記錄太多,浪費空間,而實際上在目錄中已經記錄了文件的開始簇了。所以可以改良一下,用鏈的方式來存放佔有簇的關系,變成圖 4.3.8 的組織方式。
參照圖 4.3.8 來理解一下文件分配表的意義。如文件 a.txt 我們根據目錄項中指定的 a.txt 的首簇為 2 ,然後找到文件分配表的第 2 簇記錄,上面登記的是 3 ,我們就能確定下一簇是 3 。找到文件分配表的第 3 簇記錄,上面登記的是 4 ,我們就能確定下一簇是 4...... 直到指到第 11 簇,發現下一個指向是 FF ,就是結束。文件便絲毫無誤讀取完畢。 我們再看上面提到的第三種情況,就是將 b.txt 刪除以後,存入一個大小為 60.3KB 的 d.txt 。利用簇鏈可以很容易的實現。實現後的磁盤如圖 4.3.9 4.3.10 4.3.11
上面是我們對文件存儲的一種假設,也該揭開謎底的時候了。上面的思想其實就是 fat 文件系統的思想的精髓 ( 但並不是,尤其像具體的參數的意義與我們所舉的例子是完全不同的。請忘掉上邊細節,努力記憶下邊 ) 。 ★ FAT16 存儲原理 : 當把一部分磁盤空間格式化為 fat 文件系統時, fat 文件系統就將這個分區當成整塊可分配的區域進行規劃,以便於數據的存儲。一般來講,其劃分形式如圖 7 所示。我們把 FAT16 部分提取出來,詳細描述一下: FAT16 是 Microsoft 較早推出的文件系統,具有高度兼容性,目前仍然廣泛應用於個人電腦尤其是移動存儲設備中, FAT16 簡單來講由圖 4.3.12 所示的 6 部分組成 ( 主要是前 5 部分 ) 。引導扇區 (DBR) 我們已經說過 ,FAT16 在 DBR 之後沒有留有任何保留扇區,其後緊隨的便是 FAT 表。 FAT 表是 FAT16 用來記錄磁盤數據區簇鏈結構的。像前面我們說過的例子一樣, FAT 將磁盤空間按一定數目的扇區為單位進行劃分,這樣的單位稱為簇。通常情況下,每扇區 512 字節的原則是不變的。簇的大小一般是 2n (n 為整數 ) 個扇區的大小,像 512B,1K,2K,4K,8K,16K,32K , 64K 。實際中通常不超過 32K 。 之所以簇為單位而不以扇區為單位進行磁盤的分配,是因為當分區容量較大時,采用大小為 512b 的扇區管理會增加 fat 表的項數,對大文件存取增加消耗,文件系統效率不高。分區的大小和簇的取值是有關系的,見表 9
注意:少於 32680 個扇區的分區中,簇空間大小可最多達到每個簇 8 個扇區。不管用戶是使用磁盤管理器來格式化分區,還是使用命令提示行鍵入 format 命令格式化,格式化程序都創建一個 12 位的 FAT 。少於 16MB 的分區,系統通常會將其格式化成 12 位的 FAT , FAT12 是 FAT 的初始實現形式,是針對小型介質的。 FAT12 文件分配表要比 FAT16 和 FAT32 的文件分配表小,因為它對每個條目使用的空間較少。這就給數據留下較多的空間。所有用 FAT12 格式化的 5.25 英寸軟盤以及 1.44MB 的 3.5 英寸軟盤都是由 FAT12 格式化的。除了 FAT 表中記錄每簇鏈結的二進制位數與 FAT16 不同外,其餘原理與 FAT16 均相同,不再單獨解釋。 格式化 FAT16 分區時,格式化程序根據分區的大小確定簇的大小,然後根據保留扇區的數目、根目錄的扇區數目、數據區可分的簇數與 FAT 表本身所佔空間 來確定 FAT 表所需的扇區數目,然後將計算後的結果寫入 DBR 的相關位置。 FAT16 DBR 參數的偏移 0x11 處記錄了根目錄所佔扇區的數目。偏移 0x16 記錄了 FAT 表所佔扇區的數據。偏移 0x10 記錄了 FAT 表的副本數目。系統在得到這幾項參數以後,就可以確定數據區的開始扇區偏移了。 FAT16 文件系統從根目錄所佔的 32 個扇區之後的第一個扇區開始以簇為單位進行數據的處理,這之前仍以扇區為單位。對於根目錄之後的第一個簇,系統並不編號為第 0 簇或第 1 簇 ( 可能是留作關鍵字的原因吧 ) ,而是編號為第 2 簇,也就是說數據區順序上的第 1 個簇也是編號上的第 2 簇。 FAT 文件系統之所以有 12 , 16 , 32 不同的版本之分,其根本在於 FAT 表用來記錄任意一簇鏈接的二進制位數。以 FAT16 為例,每一簇在 FAT 表中佔據 2 字節 ( 二進制 16 位 ) 。所以, FAT16 最大可以表示的簇號為 0xFFFF( 十進制的 65535) ,以 32K 為簇的大小的話, FAT32 可以管理的最大磁盤空間為: 32KB×65535=2048MB, 這就是為什麼 FAT16 不支持超過 2GB 分區的原因。 FAT 表實際上是一個數據表,以 2 個字節為單位,我們暫將這個單位稱為 FAT 記錄項,通常情況其第 1 、 2 個記錄項 ( 前 4 個字節 ) 用作介質描述。從第三個記錄項開始記錄除根目錄外的其他文件及文件夾的簇鏈情況。根據簇的表現情況 FAT 用相應的取值來描述,見表 10
看一幅在 winhex 所截 FAT16 的文件分配表,圖 10 :
如圖, FAT 表以 "F8 FF FF FF" 開頭,此 2 字節為介質描述單元,並不參與 FAT 表簇鏈關系。小紅字標出的是 FAT 扇區每 2 字節對應的簇號。 相對偏移 0x4~0x5 偏移為第 2 簇 ( 順序上第 1 簇 ) ,此處為 FF, 表示存儲在第 2 簇上的文件 ( 目錄 ) 是個小文件,只佔用 1 個簇便結束了。 第 3 簇中存放的數據是 0x0005 ,這是一個文件或文件夾的首簇。其內容為第 5 簇,就是說接下來的簇位於第 5 簇 ?D?D 〉 FAT 表指引我們到達 FAT 表的第 5 簇指向,上面寫的數據是 "FF FF", 意即此文件已至尾簇。 第 4 簇中存放的數據是 0x0006 ,這又是一個文件或文件夾的首簇。其內容為第 6 簇,就是說接下來的簇位於第 6 簇 ?D?D 〉 FAT 表指引我們到達 FAT 表的第 6 簇指向,上面寫的數據是 0x0007 ,就是說接下來的簇位於第 7 簇 ?D?D 〉 FAT 表指引我們到達 FAT 表的第 7 簇指向 …… 直到根據 FAT 鏈讀取到扇區相對偏移 0x1A~0x1B ,也就是第 13 簇,上面寫的數據是 0x000E ,也就是指向第 14 簇 ?D?D 〉 14 簇的內容為 "FF FF" ,意即此文件已至尾簇。 後面的 FAT 表數據與上面的道理相同。不再分析。 FAT 表記錄了磁盤數據文件的存儲鏈表,對於數據的讀取而言是極其重要的,以至於 Microsoft 為其開發的 FAT 文件系統中的 FAT 表創建了一份備份,就是我們看到的 FAT2 。 FAT2 與 FAT1 的內容通常是即時同步的,也就是說如果通過正常的系統讀寫對 FAT1 做了更改,那麼 FAT2 也同樣被更新。如果從這個角度來看,系統的這個功能在數據恢復時是個天災。 FAT 文件系統的目錄結構其實是一顆有向的從根到葉的樹,這裡提到的有向是指對於 FAT 分區內的任一文件 ( 包括文件夾 ) ,均需從根目錄尋址來找到。可以這樣認為:目錄存儲結構的入口就是根目錄。 FAT 文件系統根據根目錄來尋址其他文件 ( 包括文件夾 ) ,故而根目錄的位置必須在磁盤存取數據之前得以確定。 FAT 文件系統就是根據分區的相關 DBR 參數與 DBR 中存放的已經計算好的 FAT 表 (2 份 ) 的大小來確定的。格式化以後,跟目錄的大小和位置其實都已經確定下來了:位置緊隨 FAT2 之後,大小通常為 32 個扇區。根目錄之後便是數據區第 2 簇。 FAT 文件系統的一個重要思想是把目錄 ( 文件夾 ) 當作一個特殊的文件來處理, FAT32 甚至將根目錄當作文件處理 ( 旁: NTFS 將分區參數、安全權限等好多東西抽象為文件更是這個思想的昇華 ) ,在 FAT16 中,雖然根目錄地位並不等同於普通的文件或者說是目錄,但其組織形式和普通的目錄 ( 文件夾 ) 並沒有不同。 FAT 分區中所有的文件夾 ( 目錄 ) 文件,實際上可以看作是一個存放其他文件 ( 文件夾 ) 入口參數的數據表。所以目錄的佔用空間的大小並不等同於其下所有數據的大小,但也不等同於 0 。通常是佔很小的空間的,可以看作目錄文件是一個簡單的二維表文件。其具體存儲原理是: 不管目錄文件所佔空間為多少簇,一簇為多少字節。系統都會以 32 個字節為單位進行目錄文件所佔簇的分配。這 32 個字節以確定的偏移來定義本目錄下的一個文件 ( 或文件夾 ) 的屬性,實際上是一個簡單的二維表。 這 32 個字節的各字節偏移定義如表 11 :
對表 11 中的一些取值進行說明: (1) 、對於短文件名,系統將文件名分成兩部分進行存儲,即主文件名 + 擴展名。 0x0~0x7 字節記錄文件的主文件名, 0x8~0xA 記錄文件的擴展名,取文件名中的 ASCII 碼值。不記錄主文件名與擴展名之間的 "." 主文件名不足 8 個字符以空白符 (20H) 填充,擴展名不足 3 個字符同樣以空白符 (20H) 填充。 0x0 偏移處的取值若為 00H ,表明目錄項為空;若為 E5H ,表明目錄項曾被使用,但對應的文件或文件夾已被刪除。 ( 這也是誤刪除後恢復的理論依據 ) 。文件名中的第一個字符若為 『.』 或 『..』 表示這個簇記錄的是一個子目錄的目錄項。 『.』 代表當前目錄; 『..』 代表上級目錄 ( 和我們在 dos 或 windows 中的使用意思是一樣的,如果磁盤數據被破壞,就可以通過這兩個目錄項的具體參數推算磁盤的數據區的起始位置,猜測簇的大小等等,故而是比較重要的 ) (2) 、 0xB 的屬性字段:可以看作系統將 0xB 的一個字節分成 8 位,用其中的一位代表某種屬性的有或無。這樣,一個字節中的 8 位每位取不同的值就能反映各個屬性的不同取值了。如 00000101 就表示這是個文件,屬性是只讀、系統。 (3) 、 0xC~0x15 在原 FAT16 的定義中是保留未用的。在高版本的 WINDOWS 系統中有時也用它來記錄修改時間和最近訪問時間。那樣其字段的意義和 FAT32 的定義是相同的,見後邊 FAT32 。 (4) 、 0x16~0x17 中的時間 = 小時 *2048+ 分鍾 *32+ 秒 /2 。得出的結果換算成 16 進制填入即可。也就是: 0x16 字節的 0~4 位是以 2 秒為單位的量值; 0x16 字節的 5~7 位和 0x17 字節的 0~2 位是分鍾; 0x17 字節的 3~7 位是小時。 (5) 、 0x18~0x19 中的日期 =( 年份 -1980)*512+ 月份 *32+ 日。得出的結果換算成 16 進制填入即可。也就是: 0x18 字節 0~4 位是日期數; 0x18 字節 5~7 位和 0x19 字節 0 位是月份; 0x19 字節的 1~7 位為年號,原定義中 0~119 分別代表 1980~2099 ,目前高版本的 Windows 允許取 0~127 ,即年號最大可以到 2107 年。 (6) 、 0x1A~0x1B 存放文件或目錄的表示文件的首簇號,系統根據掌握的首簇號在 FAT 表中找到入口,然後再跟蹤簇鏈直至簇尾,同時用 0x1C~0x1F 處字節判定有效性。就可以完全無誤的讀取文件 ( 目錄 ) 了。 (7) 、普通子目錄的尋址過程也是通過其父目錄中的目錄項來指定的,與數據文件 ( 指非目錄文件 ) 不同的是目錄項偏移 0xB 的第 4 位置 1 ,而數據文件為 0 。 對於整個 FAT 分區而言,簇的分配並不完全總是分配乾淨的。如一個數據區為 99 個扇區的 FAT 系統,如果簇的大小設定為 2 扇區,就會有 1 個扇區無法分配給任何一個簇。這就是分區的剩餘扇區,位於分區的末尾。有的系統用最後一個剩餘扇區備份本分區的 DBR ,這也是一種好的備份方法。 早的 FAT16 系統並沒有長文件名一說, Windows 操作系統已經完全支持在 FAT16 上的長文件名了。 FAT16 的長文件名與 FAT32 長文件名的定義是相同的,關於長文件名,在 FAT32 部分再詳細作解釋。 ★ FAT32 存儲原理: FAT32 是個非常有功勞的文件系統, Microsoft 成功地設計並運用了它,直到今天 NTFS 鋪天蓋地襲來的時候, FAT32 依然佔據著 Microsoft Windows 文件系統中重要的地位。 FAT32 最早是出於 FAT16 不支持大分區、單位簇容量大以致空間急劇浪費等缺點設計的。實際應用中, FAT32 還是成功的。 FAT32 與 FAT16 的原理基本上是相同的,圖 4.3.13 標出了 FAT32 分區的基本構成。
FAT32 在格式化的過程中就根據分區的特點構建好了它的 DBR ,其中 BPB 參數是很重要的,可以回過頭來看一下表 4 和表 5 。首先 FAT32 保留扇區的數目默認為 32 個,而不是 FAT16 的僅僅一個。這樣的好處是有助於磁盤 DBR 指令的長度擴展,而且可以為 DBR 扇區留有備份空間。上面我們已經提到,構建在 FAT32 上的 win98 或 win2000 、 winXP ,其操作系統引導代碼並非只佔一個扇區了。留有多餘的保留扇區就可以很好的拓展 OS 引導代碼。在 BPB 中也記錄了 DBR 扇區的備份扇區編號。備份扇區可以讓我們在磁盤遭到意外破壞時恢復 DBR 。 FAT32 的文件分配表的數據結構依然和 FAT16 相同,所不同的是, FAT32 將記錄簇鏈的二進制位數擴展到了 32 位,故而這種文件系統稱為 FAT32 。 32 位二進制位的簇鏈決定了 FAT 表最大可以尋址 2T 個簇。這樣即使簇的大小為 1 扇區,理論上仍然能夠尋址 1TB 范圍內的分區。但實際中 FAT32 是不能尋址這樣大的空間的,隨著分區空間大小的增加, FAT 表的記錄數會變得臃腫不堪,嚴重影響系統的性能。所以在實際中通常不格式化超過 32GB 的 FAT32 分區。 WIN2000 及之上的 OS 已經不直接支持對超過 32GB 的分區格式化成 FAT32 ,但 WIN98 依然可以格式化大到 127GB 的 FAT32 分區,但這樣沒必要也不推薦。同時 FAT32 也有小的限制, FAT32 卷必須至少有 65527 個簇,所以對於小的分區,仍然需要使用 FAT16 或 FAT12 。 分區變大時,如果簇很小,文件分配表也隨之變大。仍然會有上面的效率問題存在。既要有效地讀寫大文件,又要最大可能的減少空間的浪費。 FAT32 同樣規定了相應的分區空間對應的簇的大小,見表 12 :
FAT32 簇的取值意義和 FAT16 類似,不過是位數長了點罷了,比較見表 13 : FAT32 的另一項重大改革是根目錄的文件化,即將根目錄等同於普通的文件。這樣根目錄便沒有了 FAT16 中 512 個目錄項的限制,不夠用的時候增加簇鏈,分配空簇即可。而且,根目錄的位置也不再硬性地固定了,可以存儲在分區內可尋址的任意簇內,不過通常根目錄是最早建立的 ( 格式化就生成了 ) 目錄表。所以,我們看到的情況基本上都是根目錄首簇佔簇區順序上的第 1 個簇。在圖 4.3.12 中也是按這種情況制作的畫的。 FAT32 對簇的編號依然同 FAT16 。順序上第 1 個簇仍然編號為第 2 簇,通常為根目錄所用 ( 這和 FAT16 是不同的, FAT16 的根目錄並不佔簇區空間, 32 個扇區的根目錄以後纔是簇區第 1 個簇 ) FAT32 的文件尋址方法與 FAT16 相同,但目錄項的各字節參數意義卻與 FAT16 有所不同,一方面它啟用了 FAT16 中的目錄項保留字段,同時又完全支持長文件名了。 對於短文件格式的目錄項。其參數意義見表 14 :
說明: (1) 、這是 FAT32 短文件格式目錄項的意義。其中文件名、擴展名、時間、日期的算法和 FAT16 時相同的。 (2) 、由於 FAT32 可尋址的簇號到了 32 位二進制數。所以系統在記錄文件 ( 文件夾 ) 開始簇地址的時候也需要 32 位來記錄, FAT32 啟用目錄項偏移 0x12~0x13 來表示起始簇號的高 16 位。 (3) 、文件長度依然用 4 個字節表示,這說明 FAT32 依然只支持小於 4GB 的文件 ( 目錄 ) ,超過 4GB 的文件 ( 目錄 ), 系統會截斷處理。 FAT32 的一個重要的特點是完全支持長文件名。長文件名依然是記錄在目錄項中的。為了低版本的 OS 或程序能正確讀取長文件名文件,系統自動為所有長文件名文件創建了一個對應的短文件名,使對應數據既可以用長文件名尋址,也可以用短文件名尋址。不支持長文件名的 OS 或程序會忽略它認為不合法的長文件名字段,而支持長文件名的 OS 或程序則會以長文件名為顯式項來記錄和編輯,並隱藏起短文件名。 當創建一個長文件名文件時,系統會自動加上對應的短文件名,其一般有的原則: (1) 、取長文件名的前 6 個字符加上 "~1" 形成短文件名,擴展名不變。 (2) 、如果已存在這個文件名,則符號 "~" 後的數字遞增,直到 5 。 (3) 、如果文件名中 "~" 後面的數字達到 5 ,則短文件名只使用長文件名的前兩個字母。通過數學操縱長文件名的剩餘字母生成短文件名的後四個字母,然後加後綴 "~1" 直到最後 ( 如果有必要,或是其他數字以避免重復的文件名 ) 。 (4) 、如果存在老 OS 或程序無法讀取的字符,換以 "_" 長文件名的實現有賴於目錄項偏移為 0xB 的屬性字節,當此字節的屬性為:只讀、隱藏、系統、卷標,即其值為 0FH 時, DOS 和 WIN32 會認為其不合法而忽略其存在。這正是長文件名存在的依據。將目錄項的 0xB 置為 0F ,其他就任由系統定義了, Windows9x 或 Windows 2000 、 XP 通常支持不超過 255 個字符的長文件名。系統將長文件名以 13 個字符為單位進行切割,每一組佔據一個目錄項。所以可能一個文件需要多個目錄項,這時長文件名的各個目錄項按倒序排列在目錄表中,以防與其他文件名混淆。 長文件名中的字符采用 unicode 形式編碼 ( 一個巨大的進步哦 ) ,每個字符佔據 2 字節的空間。其目錄項定義如表 15 。
系統在存儲長文件名時,總是先按倒序填充長文件名目錄項,然後緊跟其對應的短文件名。從表 15 可以看出,長文件名中並不存儲對應文件的文件開始簇、文件大小、各種時間和日期屬性。文件的這些屬性還是存放在短文件名目錄項中,一個長文件名總是和其相應的短文件名一一對應,短文件名沒有了長文件名還可以讀,但長文件名如果沒有對應的短文件名,不管什麼系統都將忽略其存在。所以短文件名是至關重要的。在不支持長文件名的環境中對短文件名中的文件名和擴展名字段作更改 ( 包括刪除,因為刪除是對首字符改寫 E5H) ,都會使長文件名形同虛設。長文件名和短文件名之間的聯系光靠他們之間的位置關系維系顯然遠遠不夠。其實,長文件名的 0xD 字節的校驗和起很重要的作用,此校驗和是用短文件名的 11 個字符通過一種運算方式來得到的。系統根據相應的算法來確定相應的長文件名和短文件名是否匹配。這個算法不太容易用公式說明,我們用一段 c 程序來加以說明。 假設文件名 11 個字符組成字符串 shortname[], 校驗和用 chknum 表示。得到過程如下: int i , j,chknum=0; 如果通過短文件名計算出來的校驗和與長文件名中的 0xD 偏移處數據不相等。系統無論如何都不會將它們配對的。 依據長文件名和短文件名對目錄項的定義,加上對簇的編號和鏈接, FAT32 上數據的讀取便游刃有餘了。
|
電話:0086-0595-22841608 013305960800 E-mail:Cailvjin WWW.TL800.COM |
||||||||||||