★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上數據的讀取便遊刃有餘了。
五、結束。
本文出自數據恢復網(www.sjhf.net),疏漏在所難免,希望指正。若需轉載請保留此信息;若需修改,請用以下方式與作者取得聯繫 1、http://www.sjhf.net 2、[email protected] 3、[email protected]
單擊此處查看PDF版全文
|