[轉自] http://www.sjhf.net/Article/sjhfdoc/200404/1.html
- 一、硬盤的物理結構:
硬盤存儲數據是根據電、磁轉換原理實現的。硬盤由一個或幾個表面鍍有磁性物質的金屬或玻璃等物質盤片以及盤片兩面所安裝的磁頭和相應的控制電路組成(圖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。
表1 圖2分區表第一字段 | |||
字節位移 | 字段長度 | 值 | 字段名和定義 |
0x01BE | BYTE | 0x80 | 引導指示符(Boot Indicator) 指明該分區是否是活動分區。 |
0x01BF | BYTE | 0x01 | 開始磁頭(Starting Head) |
0x01C0 | 6位 | 0x01 | 開始扇區(Starting Sector) 只用了0~5位。后面的兩位(第6位和第7位)被開始柱面字段所使用 |
0x01C1 | 10位 | 0x00 | 開始柱面(Starting Cylinder) 除了開始扇區字段的最后兩位外,還使用了1位來組成該柱面值。開始柱面是一個10位數,最大值為1023 |
0x01C2 | BYTE | 0x07 | 系統ID(System ID) 定義了分區的類型,詳細定義,請參閱圖4 |
0x01C3 | BYTE | 0xFE | 結束磁頭(Ending Head) |
0x01C4 | 6位 | 0xFF | 結束扇區(Ending Sector) 只使用了0~5位。最后兩位(第6、7位)被結束柱面字段所使用 |
0x01C5 | 10位 | 0x7B | 結束柱面(Ending Cylinder) 除了結束扇區字段最后的兩位外,還使用了1位,以組成該柱面值。結束柱面是一個10位的數,最大值為1023 |
0x01C6 | DWORD | 0x0000003F | 相對扇區數(Relative Sectors) 從該磁盤的開始到該分區的開始的位移量,以扇區來計算 |
0x01CA | DWORD | 0x00DAA83D | 總扇區數(Total Sectors) 該分區中的扇區總數 |
注:上表中的超過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。最后一個邏輯驅動器的擴展分區表只會列出它本身的分區項。最后一個擴展分區表的第二個項到第四個項被使用。
表2 擴展分區表項的內容 |
|
擴展分區表項 | 分區表項的內容 |
第一個項 | 包括數據的開始地址在內的與擴展分區中當前邏輯驅動器有關的信息 |
第二個項 | 有關擴展分區中的下一個邏輯驅動器的信息,包括包含下一個邏輯驅動器的EBR的扇區的地址。如果不存在進一步的邏輯驅動器的話,該字段不會被使用 |
第三個項 | 未用 |
第四個項 | 未用 |
擴展分區表項中的相對扇區數字段所顯示的是從擴展分區開始到邏輯驅動器中第一個扇區的位移的字節數。總扇區數字段中的數是指組成該邏輯驅動器的扇區數目。總扇區數字段的值等於從擴展分區表項所定義的引導扇區到邏輯驅動器末尾的扇區數。
有時候在磁盤的末尾會有剩余空間,剩余空間是什么呢?我們前面說到,分區是以1柱面的容量為分區粒度的,那么如果磁盤總空間不是整數個柱面的話,不夠一個 柱面的剩下的空間就是剩余空間了,這部分空間並不參與分區,所以一般無法利用。照道理說,磁盤的物理模式決定了磁盤的總容量就應該是整數個柱面的容量,為 什么會有不夠一個柱面的空間呢。在我的理解看來,本來現在的磁盤為了更大的利用空間,一般在物理上並不是按照外圍的扇區大於里圈的扇區這種管理方式,只是 為了與操作系統兼容而抽象出來CHS。可能其實際空間容量不一定正好為整數個柱面的容量吧。關於這點,如有高見,請告知http://www.sjhf.net或zymail@vip.sina.com,sjhf@sjhf.net。
- 四、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
表3 FAT32分區上DBR中各部分的位置划分 | |||
字節位移 | 字段長度 | 字段名 | 對應圖8顏色 |
0x00 | 3個字節 | 跳轉指令 | |
0x03 | 8個字節 | 廠商標志和os版本號 | |
0x0B | 53個字節 | BPB | |
0x40 | 26個字節 | 擴展BPB | |
0x5A | 420個字節 | 引導程序代碼 | |
0x01FE | 2個字節 | 有效結束標志 |
圖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。
表4 FAT32分區的BPB字段 | |||
字節位移 | 字段長度(字節) | 圖8對應取值 | 名稱和定義 |
0x0B | 2 | 0x0200 | 扇區字節數(Bytes Per Sector) 硬件扇區的大小。本字段合法的十進制值有512、1024、2048和4096。對大多數磁盤來說,本字段的值為512 |
0x0D | 1 | 0x08 | 每簇扇區數 (Sectors Per Cluster),一簇中的扇區數。由於FAT32文件系統只能跟蹤有限個簇(最多為4 294 967 296個),因此,通過增加每簇扇區數,可以使FAT32文件系統支持最大分區數。一個分區缺省的簇大小取決於該分區的大小。本字段的合法十進制值有1、 2、4、8、16、32、64和128。Windows 2000的FAT32實現只能創建最大為32GB的分區。但是,Windows 2000能夠訪問由其他操作系統(Windows 95、OSR2及其以后的版本)所創建的更大的分區 |
0x0e | 2 | 0x0020 | 保留扇區數(Reserved Sector) 第一個FAT開始之前的扇區數,包括引導扇區。本字段的十進制值一般為32 |
0x10 | 1 | 0x02 | FAT數(Number of FAT) 該分區上FAT的副本數。本字段的值一般為2 |
0x11 | 2 | 0x0000 | 根目錄項數(Root Entries)只有FAT12/FAT16使用此字段。對FAT32分區而言,本字段必須設置為 0 |
0x13 | 2 | 0x0000 | 小扇區數(Small Sector)(只有FAT12/FAT16使用此字段)對FAT32分區而言,本字段必須設置為0 |
0x15 | 1 | 0xF8 | 媒體描述符( Media Descriptor)提供有關媒體被使用的信息。值0xF8表示硬盤,0xF0表示高密度的3.5寸軟盤。媒體描述符要用於MS-DOS FAT16磁盤,在Windows 2000中未被使用 |
0x16 | 2 | 0x0000 | 每FAT扇區數(Sectors Per FAT)只被FAT12/FAT16所使用,對FAT32分區而言,本字段必須設置為0 |
0x18 | 2 | 0x003F | 每道扇區數(Sectors Per Track) 包含使用INT13h的磁盤的“每道扇區數”幾何結構值。該分區被多個磁頭的柱面分成了多個磁道 |
0x1A | 2 | 0x00FF | 磁頭數(Number of Head) 本字段包含使用INT 13h的磁盤的“磁頭數”幾何結構值。例如,在一張1.44MB 3.5英寸的軟盤上,本字段的值為 2 |
0x1C | 4 | 0x0000003F | 隱藏扇區數(Hidden Sector) 該分區上引導扇區之前的扇區數。在引導序列計算到根目錄的數據區的絕對位移的過程中使用了該值。本字段一般只對那些在中斷13h上可見的媒體有意義。在沒有分區的媒體上它必須總是為0 |
0x20 | 4 | 0x007D043F | 總扇區數(Large Sector) 本字段包含FAT32分區中總的扇區數 |
0x24 | 4 | 0x00001F32 | 每FAT扇區數(Sectors Per FAT)(只被FAT32使用)該分區每個FAT所占的扇區數。計算機利用這個數和 FAT數以及隱藏扇區數(本表中所描述的)來決定根目錄從哪里開始。該計算機還可以從目錄中的項數決定該分區的用戶數據區從哪里開始 |
0x28 | 2 | 0x00 | 擴展標志(Extended Flag)(只被FAT32使用)該兩個字節結構中各位的值為: |
0x2A | 2 | 0x0000 | 文件系統版本(File ystem Version)只供FAT32使用,高字節是主要的修訂號,而低字節是次要的修訂號。本字段支持將來對該FAT32媒體類型進行擴展。如果本字段非零,以前的Windows版本將不支持這樣的分區 |
0x2C | 4 | 0x00000002 | 根目錄簇號(Root Cluster Number)(只供FAT32使用) 根目錄第一簇的簇號。本字段的值一般為2,但不總是如此 |
0x30 | 2 | 0x0001 | 文件系統信息扇區號 (File System Information SectorNumber)(只供FAT32使用) FAT32分區的保留區中的文件系統信息(File System Information, FSINFO)結構的扇區號。其值一般為1。在備份引導扇區(Backup Boot Sector)中保留了該FSINFO結構的一個副本,但是這個副本不保持更新 |
0x34 | 2 | 0x0006 | 備份引導扇區(只供FAT32使用) 為一個非零值,這個非零值表示該分區保存引導扇區的副本的保留區中的扇區號。本字段的值一般為6,建議不要使用其他值 |
0x36 | 12 | 12個字節均為0x00 | 保留(只供FAT32使用)供以后擴充使用的保留空間。本字段的值總為0 |
表5 FAT32分區的擴展BPB字段 | |||
字節位移 | 字段長度(字節) | 圖8對應取值 | 字段名稱和定義 |
0x40 | 1 | 0x80 | 物理驅動器號( Physical Drive Number) 與BIOS物理驅動器號有關。軟盤驅動器被標識為0x00,物理硬盤被標識為0x80,而與物理磁盤驅動器無關。一般地,在發出一個INT13h BIOS調用之前設置該值,具體指定所訪問的設備。只有當該設備是一個引導設備時,這個值才有意義 |
0x41 | 1 | 0x00 | 保留(Reserved) FAT32分區總是將本字段的值設置為0 |
0x42 | 1 | 0x29 | 擴展引導標簽(Extended Boot Signature) 本字段必須要有能被Windows 2000所識別的值0x28或0x29 |
0x43 | 4 | 0x33391CFE | 分區序號(Volume Serial Number) 在格式化磁盤時所產生的一個隨機序號,它有助於區分磁盤 |
0x47 | 11 | "NO NAME" | 卷標(Volume Label) 本字段只能使用一次,它被用來保存卷標號。現在,卷標被作為一個特殊文件保存在根目錄中 |
0x52 | 8 | "FAT32" | 系統ID(System ID) FAT32文件系統中一般取為"FAT32" |
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大同小異的。
表6 一個FAT16分區上的引導扇區段 | ||
字節位移 | 字段長度(字節) | 字段名稱 |
0x00 | 3 | 跳轉指令(Jump Instruction) |
0x03 | 8 | OEM ID |
0x0B | 25 | BPB |
0x24 | 26 | 擴展BPB |
0x3E | 448 | 引導程序代碼(Bootstrap Code) |
0x01FE | 4 | 扇區結束標識符(0x55AA) |
表7 FAT16分區的BPB字段 | |||
字節位移 | 字段長度(字節) | 例值 | 名稱和定義 |
0x0B | 2 | 0x0200 | 扇區字節數(Bytes Per Sector) 硬件扇區的大小。本字段合法的十進制值有512、1024、2048和4096。對大多數磁盤來說,本字段的值為512 |
0x0D | 1 | 0x40 | 每簇扇區數 (Sectors Per Cluster) 一個簇中的扇區數。由於FAT16文件系統只能跟蹤有限個簇(最多為65536個)。因此,通過增加每簇的扇區數可以支持最大分區數。分區的缺省的簇的大 小取決於該 分區的大小。本字段合法的十進制值有 1、2、4、8、16、32、64和128。導致簇大於32KB(每扇區字節數*每簇扇區數)的值會引起磁盤錯誤和軟件錯誤 |
0x0e | 2 | 0x0001 | 保留扇區數(Reserved Sector) 第一個FAT開始之前的扇區數,包括引導扇區。本字段的十進制值一般為1 |
0x10 | 1 | 0x02 | FAT數(Number of FAT)該分區上FAT的副本數。本字段的值一般為2 |
0x11 | 2 | 0x0200 | 根目錄項數 (Root Entries) 能夠保存在該分區的根目錄文件夾中的32個字節長的文件和文件夾名稱項的總數。在一個典型的硬盤上,本字段的值為512。其中一個項常常被用作卷標號 (Volume Label),長名稱的文件和文件夾每個文件使用多個項。文件和文件夾項的最大數一般為511,但是如果使用的長文件名,往往都達不到這個數 |
0x13 | 2 | 0x0000 | 小扇區數(Small Sector) 該分區上的扇區數,表示為16位(<65536)。對大於65536個扇區的分區來說,本字段的值為0,而使用大扇區數來取代它 |
0x15 | 1 | 0xF8 | 媒體描述符( Media Descriptor)提供有關媒體被使用的信息。值0xF8表示硬盤,0xF0表示高密度的3.5寸軟盤。媒體描述符要用於MS-DOS FAT16磁盤,在Windows 2000中未被使用 |
0x16 | 2 | 0x00FC | 每FAT扇區數(Sectors Per FAT) 該分區上每個FAT所占用的扇區數。計算機利用這個數和FAT數以及隱藏扇區數來決定根目錄在哪里開始。計算機還可以根據根目錄中的項數(512)決定該 分區的用戶數據區從哪里開始 |
0x18 | 2 | 0x003F | 每道扇區數(Sectors Per Trark) |
0x1A | 2 | 0x0040 | 磁頭數(Number of head) |
0x1C | 4 | 0x0000003F | 隱藏扇區數(Hidden Sector) 該分區上引導扇區之前的扇區數。在引導序列計算到根目錄和數據區的絕對位移的過程中使用了該值 |
0x20 | 4 | 0x003EF001 | 大扇區數(Large Sector) 如果小扇區數字段的值為0,本字段就包含該FAT16分區中的總扇區數。如果小扇區數字段的值不為0,那么本字段的值為0 |
表8 FAT16分區的擴展BPB字段 | |||
字節位移 | 字段長度(字節) | 圖8對應取值 | 字段名稱和定義 |
0x24 | 1 | 0x80 | 物理驅動器號( Physical Drive Number) 與BIOS物理驅動器號有關。軟盤驅動器被標識為0x00,物理硬盤被標識為0x80,而與物理磁盤驅動器無關。一般地,在發出一個INT13h BIOS調用之前設置該值,具體指定所訪問的設備。只有當該設備是一個引導設備時,這個值才有意義 |
0x25 | 1 | 0x00 | 保留(Reserved) FAT16分區一般將本字段的值設置為0 |
0x26 | 1 | 0x29 | 擴展引導標簽(Extended Boot Signature) 本字段必須要有能被Windows 2000所識別的值0x28或0x29 |
0x27 | 2 | 0x52368BA8 | 卷序號(Volume Serial Number) 在格式化磁盤時所產生的一個隨機序號,它有助於區分磁盤 |
0x2B | 11 | "NO NAME" | 卷標(Volume Label) 本字段只能使用一次,它被用來保存卷標號。現在,卷標被作為一個特殊文件保存在根目錄中 |
0x36 | 8 | "FAT16" | 文件系統類型(File System Type) 根據該磁盤格式,該字段的值可以為FAT、FAT12或FAT16 |
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文件系統將組織數據時使用的目錄也抽象為文件,以簡化對數據的管理。
單擊此處查看PDF版全文
★存儲過程假想:
我們模擬對一個分區存儲數據的過程來說明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.11所示的6部分組成(主要是前5部分)。引導扇區(DBR)我們已經說過,FAT16在DBR之后沒有留有任何保留扇區,其后緊隨的便是FAT 表。FAT表是FAT16用來記錄磁盤數據區簇鏈結構的。像前面我們說過的例子一樣,FAT將磁盤空間按一定數目的扇區為單位進行划分,這樣的單位稱為 簇。通常情況下,每扇區512字節的原則是不變的。簇的大小一般是2n (n為整數)個扇區的大小,像 512B,1K,2K,4K,8K,16K,32K,64K。實際中通常不超過32K。 之所以簇為單位而不以扇區為單位進行磁盤的分配,是因為當分區容量較大時,采用大小為512b的扇區管理會增加fat表的項數,對大文件存取增加消耗,文 件系統效率不高。分區的大小和簇的取值是有關系的,見表9 (單擊此處查看PDF版全文)
圖4.3.11 Fat16的組織形式 | |||||
引導扇區 | FAT1 | FAT2(重復的) | 根文件夾 | 其他文件夾及所有文件 | 剩余扇區 |
1扇區 | 實際情況取大小 | 同FAT1 | 32個扇區 | 開始簇編號(從2開始) | 不足一簇 |
表9 FAT16分區大小與對因簇大小 | ||
分區空間大小 | 每個簇的扇區 | 簇空間大小 |
0MB-32MB | 1 | 512個字節 |
33MB-64MB | 2 | 1k |
65MB-128MB | 4 | 2k |
129MB-225MB | 8 | 4k |
256MB-511MB | 16 | 8k |
512MB-1023MB | 32 | 16k |
1024MB-2047MB | 64 | 32k |
2048MB-4095MB | 128 | 64k |
注意:少於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
表10 FAT16記錄項的取值含義(16進制) | |
FAT16記錄項的取值 | 對應簇的表現情況 |
0000 | 未分配的簇 |
0002~FFEF | 已分配的簇 |
FFF0~FFF6 | 系統保留 |
FFF7 | 壞簇 |
FFF8~FFFF | 文件結束簇 |
看一幅在winhex所截FAT16的文件分配表,圖10:
如圖,FAT表以"F8 FF FF FF" 開頭,此2字節為介質描述單元,並不參與FAT表簇鏈關系。小紅字標出的是FAT扇區每2字節對應的簇號。
相對偏移0x4~0x5偏移為第2簇(順序上第1簇),此處為FF,表示存儲在第2簇上的文件(目錄)是個小文件,只占用1個簇便結束了。
第3簇中存放的數據是0x0005,這是一個文件或文件夾的首簇。其內容為第5簇,就是說接下來的簇位於第5簇——〉 FAT表指引我們到達FAT表的第5簇指向,上面寫的數據是"FF FF",意即此文件已至尾簇。
第4簇中存放的數據是0x0006,這又是一個文件或文件夾的首簇。其內容為第6簇,就是說接下來的簇位於第6簇——〉FAT表指引我們到達FAT表的第 6簇指向,上面寫的數據是0x0007,就是說接下來的簇位於第7簇——〉FAT表指引我們到達FAT表的第7簇指向……直到根據FAT鏈讀取到扇區相對 偏移0x1A~0x1B,也就是第13簇,上面寫的數據是0x000E,也就是指向第14簇——〉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 FAT16目錄項32個字節的表示定義 | |||
字節偏移(16進制) | 字節數 | 定義 | |
0x0~0x7 | 8 | 文件名 | |
0x8~0xA | 3 | 擴展名 | |
0xB | 1 | 屬性字節 | 00000000(讀寫) |
00000001(只讀) | |||
00000010(隱藏) | |||
00000100(系統) | |||
00001000(卷標) | |||
00010000(子目錄) | |||
00100000(歸檔) | |||
0xC~0x15 | 10 | 系統保留 | |
0x16~0x17 | 2 | 文件的最近修改時間 | |
0x18~0x19 | 2 | 文件的最近修改日期 | |
0x1A~0x1B | 2 | 表示文件的首簇號 | |
0x1C~0x1F | 4 | 表示文件的長度 |
對圖10中的一些取值進行說明:
(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.12標出了FAT32分區的基本構成。
圖4.3.12 Fat32的組織形式 | ||||||
引導扇區 | 其余保留扇區 | FAT1 | FAT2(重復的) | 根文件夾首簇 | 其他文件夾及所有文件 | 剩余扇區 |
1扇區 | 31個扇區 | 實際情況取大小 | 同FAT1 | 第2簇 | 不足一簇 | |
保留扇區 | ┗━━━━━━━━數據區━━━━━━━━┛ |
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:
表12 FAT32分區大小與對因簇大小 | ||
分區空間大小 | 每個簇的扇區 | 簇空間大小 |
<8GB | 8 | 4k |
>=8GB且<16GB | 16 | 8k |
>=16GB且<32GB | 32 | 16k |
>=32GB | 64 | 32k |
簇的取值意義和FAT16類似,不過是位數長了點罷了,比較見表13:
表13 FAT各系統記錄項的取值含義(16進制) | |||
FAT12記錄項的取值 | FAT16記錄項的取值 | FAT32記錄項的取值 | 對應簇的表現情況 |
000 | 0000 | 00000000 | 未分配的簇 |
002~FFF | 0002~FFEF | 00000002~FFFFFFEF | 已分配的簇 |
FF0~FF6 | FFF0~FFF6 | FFFFFFF0~FFFFFFF6 | 系統保留 |
FF7 | FFF7 | FFFFFFF7 | 壞簇 |
FF8~FFF | FFF8~FFFF | FFFFFFF8~FFFFFFFF | 文件結束簇 |
FAT32的另一項重大改革是根目錄的文件化,即將根目錄等同於普通的文件。這樣根目錄便沒有了FAT16中512個目錄項的限制,不夠用的時候增加簇 鏈,分配空簇即可。而且,根目錄的位置也不再硬性地固定了,可以存儲在分區內可尋址的任意簇內,不過通常根目錄是最早建立的(格式化就生成了)目錄表。所 以,我們看到的情況基本上都是根目錄首簇占簇區順序上的第1個簇。在圖4.3.12中也是按這種情況制作的畫的。
FAT32對簇的編號依然同FAT16。順序上第1個簇仍然編號為第2簇,通常為根目錄所用(這和FAT16是不同的,FAT16的根目錄並不占簇區空間,32個扇區的根目錄以后才是簇區第1個簇)
FAT32的文件尋址方法與FAT16相同,但目錄項的各字節參數意義卻與FAT16有所不同,一方面它啟用了FAT16中的目錄項保留字段,同時又完全支持長文件名了。
對於短文件格式的目錄項。其參數意義見表14:
表14 FAT32短文件目錄項32個字節的表示定義 | |||
字節偏移(16進制) | 字節數 | 定義 | |
0x0~0x7 | 8 | 文件名 | |
0x8~0xA | 3 | 擴展名 | |
0xB* | 1 | 屬性字節 | 00000000(讀寫) |
00000001(只讀) | |||
00000010(隱藏) | |||
00000100(系統) | |||
00001000(卷標) | |||
00010000(子目錄) | |||
00100000(歸檔) | |||
0xC | 1 | 系統保留 | |
0xD | 1 | 創建時間的10毫秒位 | |
0xE~0xF | 2 | 文件創建時間 | |
0x10~0x11 | 2 | 文件創建日期 | |
0x12~0x13 | 2 | 文件最后訪問日期 | |
0x14~0x15 | 2 | 文件起始簇號的高16位 | |
0x16~0x17 | 2 | 文件的最近修改時間 | |
0x18~0x19 | 2 | 文件的最近修改日期 | |
0x1A~0x1B | 2 | 文件起始簇號的低16位 | |
0x1C~0x1F | 4 | 表示文件的長度 |
* 此字段在短文件目錄項中不可取值0FH,如果設值為0FH,目錄段為長文件名目錄段 |
說明:
(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 FAT32長文件目錄項32個字節的表示定義 | ||||
字節偏移 (16進制) |
字節數 | 定義 | ||
0x0 | 1 | 屬性字節位意義 | 7 | 保留未用 |
6 | 1表示長文件最后一個目錄項 | |||
5 | 保留未用 | |||
4 | 順序號數值 | |||
3 | ||||
2 | ||||
1 | ||||
0 | ||||
0x1~0xA | 10 | 長文件名unicode碼① | ||
0xB | 1 | 長文件名目錄項標志,取值0FH | ||
0xC | 1 | 系統保留 | ||
0xD | 1 | 校驗值(根據短文件名計算得出) | ||
0xE~0x19 | 12 | 長文件名unicode碼② | ||
0x1A~0x1B | 2 | 文件起始簇號(目前常置0) | ||
0x1C~0x1F | 4 | 長文件名unicode碼③ |
系統在存儲長文件名時,總是先按倒序填充長文件名目錄 項,然后緊跟其對應的短文件名。從表15可以看出,長文件名中並不存儲對應文件的文件開始簇、文件大小、各種時間和日期屬性。文件的這些屬性還是存放在短 文件名目錄項中,一個長文件名總是和其相應的短文件名一一對應,短文件名沒有了長文件名還可以讀,但長文件名如果沒有對應的短文件名,不管什么系統都將忽 略其存在。所以短文件名是至關重要的。在不支持長文件名的環境中對短文件名中的文件名和擴展名字段作更改(包括刪除,因為刪除是對首字符改寫E5H),都 會使長文件名形同虛設。長文件名和短文件名之間的聯系光靠他們之間的位置關系維系顯然遠遠不夠。其實,長文件名的0xD字節的校驗和起很重要的作用,此校 驗和是用短文件名的11個字符通過一種運算方式來得到的。系統根據相應的算法來確定相應的長文件名和短文件名是否匹配。這個算法不太容易用公式說明,我們 用一段c程序來加以說明。
假設文件名11個字符組成字符串shortname[],校驗和用chknum表示。得到過程如下:
int i,j,chknum=0;
for (i=11; i>0; i--)
chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];
如果通過短文件名計算出來的校驗和與長文件名中的0xD偏移處數據不相等。系統無論如何都不會將它們配對的。
依據長文件名和短文件名對目錄項的定義,加上對簇的編號和鏈接,FAT32上數據的讀取便游刃有余了