FAT32存儲(chǔ)原理:
FAT32是個(gè)非常有功勞的文件系統(tǒng),Microsoft成功地設(shè)計(jì)并運(yùn)用了它,直到今天NTFS鋪天蓋地襲來(lái)的時(shí)候,F(xiàn)AT32依然占據(jù)著Microsoft Windows文件系統(tǒng)中重要的地位。FAT32最早是出于FAT16不支持大分區(qū)、單位簇容量大以致空間急劇浪費(fèi)等缺點(diǎn)設(shè)計(jì)的。實(shí)際應(yīng)用中,F(xiàn)AT32還是成功的。
FAT32與FAT16的原理基本上是相同的,圖4.3.12標(biāo)出了FAT32分區(qū)的基本構(gòu)成。
圖4.3.12 Fat32的組織形式
引導(dǎo)扇區(qū) 其余保留扇區(qū) FAT1 FAT2(重復(fù)的) 根文件夾首簇 其他文件夾及所有文件 剩余扇區(qū)
1扇區(qū) 31個(gè)扇區(qū) 實(shí)際情況取大小 同F(xiàn)AT1 第2簇 不足一簇
保留扇區(qū) ┗━━━━━━━━數(shù)據(jù)區(qū)━━━━━━━━┛
FAT32在格式化的過(guò)程中就根據(jù)分區(qū)的特點(diǎn)構(gòu)建好了它的DBR,其中BPB參數(shù)是很重要的,可以回過(guò)頭來(lái)看一下表4和表5。首先FAT32保留扇區(qū)的數(shù)目默認(rèn)為32個(gè),而不是FAT16的僅僅一個(gè)。這樣的好處是有助于磁盤(pán)DBR指令的長(zhǎng)度擴(kuò)展,而且可以為DBR扇區(qū)留有備份空間。上面我們已經(jīng)提到,構(gòu)建在FAT32上的win98或win2000、winXP,其操作系統(tǒng)引導(dǎo)代碼并非只占一個(gè)扇區(qū)了。留有多余的保留扇區(qū)就可以很好的拓展OS引導(dǎo)代碼。在BPB中也記錄了DBR扇區(qū)的備份扇區(qū)編號(hào)。備份扇區(qū)可以讓我們?cè)诖疟P(pán)遭到意外破壞時(shí)恢復(fù)DBR。
FAT32的文件分配表的數(shù)據(jù)結(jié)構(gòu)依然和FAT16相同,所不同的是,F(xiàn)AT32將記錄簇鏈的二進(jìn)制位數(shù)擴(kuò)展到了32位,故而這種文件系統(tǒng)稱(chēng)為FAT32。32位二進(jìn)制位的簇鏈決定了FAT表最大可以尋址2T個(gè)簇。這樣即使簇的大小為1扇區(qū),理論上仍然能夠?qū)ぶ?TB范圍內(nèi)的分區(qū)。但實(shí)際中FAT32是不能尋址這樣大的空間的,隨著分區(qū)空間大小的增加,F(xiàn)AT表的記錄數(shù)會(huì)變得臃腫不堪,嚴(yán)重影響系統(tǒng)的性能。所以在實(shí)際中通常不格式化超過(guò)32GB的FAT32分區(qū)。WIN2000及之上的OS已經(jīng)不直接支持對(duì)超過(guò)32GB的分區(qū)格式化成FAT32,但WIN98依然可以格式化大到127GB的FAT32分區(qū),但這樣沒(méi)必要也不推薦。同時(shí)FAT32也有小的限制,F(xiàn)AT32卷必須至少有65527個(gè)簇,所以對(duì)于小的分區(qū),仍然需要使用FAT16或FAT12。
分區(qū)變大時(shí),如果簇很小,文件分配表也隨之變大。仍然會(huì)有上面的效率問(wèn)題存在。既要有效地讀寫(xiě)大文件,又要最大可能的減少空間的浪費(fèi)。FAT32同樣規(guī)定了相應(yīng)的分區(qū)空間對(duì)應(yīng)的簇的大小,見(jiàn)表12:
表12 FAT32分區(qū)大小與對(duì)因簇大小
分區(qū)空間大小 每個(gè)簇的扇區(qū) 簇空間大小
<8GB 8 4k
>=8GB且<16GB 16 8k
>=16GB且<32GB 32 16k
>=32GB 64 32k
簇的取值意義和FAT16類(lèi)似,不過(guò)是位數(shù)長(zhǎng)了點(diǎn)罷了,比較見(jiàn)表13:
表13 FAT各系統(tǒng)記錄項(xiàng)的取值含義(16進(jìn)制)
FAT12記錄項(xiàng)的取值 FAT16記錄項(xiàng)的取值 FAT32記錄項(xiàng)的取值 對(duì)應(yīng)簇的表現(xiàn)情況
000 0000 00000000 未分配的簇
002~FFF 0002~FFEF 00000002~FFFFFFEF 已分配的簇
FF0~FF6 FFF0~FFF6 FFFFFFF0~FFFFFFF6 系統(tǒng)保留
FF7 FFF7 FFFFFFF7 壞簇
FF8~FFF FFF8~FFFF FFFFFFF8~FFFFFFFF 文件結(jié)束簇
FAT32的另一項(xiàng)重大改革是根目錄的文件化,即將根目錄等同于普通的文件。這樣根目錄便沒(méi)有了FAT16中512個(gè)目錄項(xiàng)的限制,不夠用的時(shí)候增加簇鏈,分配空簇即可。而且,根目錄的位置也不再硬性地固定了,可以存儲(chǔ)在分區(qū)內(nèi)可尋址的任意簇內(nèi),不過(guò)通常根目錄是最早建立的(格式化就生成了)目錄表。所以,我們看到的情況基本上都是根目錄首簇占簇區(qū)順序上的第1個(gè)簇。在圖4.3.12中也是按這種情況制作的畫(huà)的。
FAT32對(duì)簇的編號(hào)依然同F(xiàn)AT16。順序上第1個(gè)簇仍然編號(hào)為第2簇,通常為根目錄所用(這和FAT16是不同的,F(xiàn)AT16的根目錄并不占簇區(qū)空間,32個(gè)扇區(qū)的根目錄以后才是簇區(qū)第1個(gè)簇)
FAT32的文件尋址方法與FAT16相同,但目錄項(xiàng)的各字節(jié)參數(shù)意義卻與FAT16有所不同,一方面它啟用了FAT16中的目錄項(xiàng)保留字段,同時(shí)又完全支持長(zhǎng)文件名了。
對(duì)于短文件格式的目錄項(xiàng)。其參數(shù)意義見(jiàn)表14:
表14 FAT32短文件目錄項(xiàng)32個(gè)字節(jié)的表示定義
字節(jié)偏移(16進(jìn)制) 字節(jié)數(shù) 定義
0x0~0x7 8 文件名
0x8~0xA 3 擴(kuò)展名
0xB* 1 屬性字節(jié) 00000000(讀寫(xiě))
00000001(只讀)
00000010(隱藏)
00000100(系統(tǒng))
00001000(卷標(biāo))
00010000(子目錄)
00100000(歸檔)
0xC 1 系統(tǒng)保留
0xD 1 創(chuàng)建時(shí)間的10毫秒位
0xE~0xF 2 文件創(chuàng)建時(shí)間
0x10~0x11 2 文件創(chuàng)建日期
0x12~0x13 2 文件最后訪(fǎng)問(wèn)日期
0x14~0x15 2 文件起始簇號(hào)的高16位
0x16~0x17 2 文件的最近修改時(shí)間
0x18~0x19 2 文件的最近修改日期
0x1A~0x1B 2 文件起始簇號(hào)的低16位
0x1C~0x1F 4 表示文件的長(zhǎng)度
* 此字段在短文件目錄項(xiàng)中不可取值0FH,如果設(shè)值為0FH,目錄段為長(zhǎng)文件名目錄段
說(shuō)明:
(1)、這是FAT32短文件格式目錄項(xiàng)的意義。其中文件名、擴(kuò)展名、時(shí)間、日期的算法和FAT16時(shí)相同的。
(2)、由于FAT32可尋址的簇號(hào)到了32位二進(jìn)制數(shù)。所以系統(tǒng)在記錄文件(文件夾)開(kāi)始簇地址的時(shí)候也需要32位來(lái)記錄,F(xiàn)AT32啟用目錄項(xiàng)偏移0x12~0x13來(lái)表示起始簇號(hào)的高16位。
(3)、文件長(zhǎng)度依然用4個(gè)字節(jié)表示,這說(shuō)明FAT32依然只支持小于4GB的文件(目錄),超過(guò)4GB的文件(目錄),系統(tǒng)會(huì)截?cái)嗵幚怼?BR> FAT32的一個(gè)重要的特點(diǎn)是完全支持長(zhǎng)文件名。長(zhǎng)文件名依然是記錄在目錄項(xiàng)中的。為了低版本的OS或程序能正確讀取長(zhǎng)文件名文件,系統(tǒng)自動(dòng)為所有長(zhǎng)文件名文件創(chuàng)建了一個(gè)對(duì)應(yīng)的短文件名,使對(duì)應(yīng)數(shù)據(jù)既可以用長(zhǎng)文件名尋址,也可以用短文件名尋址。不支持長(zhǎng)文件名的OS或程序會(huì)忽略它認(rèn)為不合法的長(zhǎng)文件名字段,而支持長(zhǎng)文件名的OS或程序則會(huì)以長(zhǎng)文件名為顯式項(xiàng)來(lái)記錄和編輯,并隱藏起短文件名。
當(dāng)創(chuàng)建一個(gè)長(zhǎng)文件名文件時(shí),系統(tǒng)會(huì)自動(dòng)加上對(duì)應(yīng)的短文件名,其一般有的原則:
(1)、取長(zhǎng)文件名的前6個(gè)字符加上"~1"形成短文件名,擴(kuò)展名不變。
(2)、如果已存在這個(gè)文件名,則符號(hào)"~"后的數(shù)字遞增,直到5。
(3)、如果文件名中"~"后面的數(shù)字達(dá)到5,則短文件名只使用長(zhǎng)文件名的前兩個(gè)字母。通過(guò)數(shù)學(xué)操縱長(zhǎng)文件名的剩余字母生成短文件名的后四個(gè)字母,然后加后綴"~1"直到最后(如果有必要,或是其他數(shù)字以避免重復(fù)的文件名)。
(4)、如果存在老OS或程序無(wú)法讀取的字符,換以"_"
長(zhǎng)文件名的實(shí)現(xiàn)有賴(lài)于目錄項(xiàng)偏移為0xB的屬性字節(jié),當(dāng)此字節(jié)的屬性為:只讀、隱藏、系統(tǒng)、卷標(biāo),即其值為0FH時(shí),DOS和WIN32會(huì)認(rèn)為其不合法而忽略其存在。這正是長(zhǎng)文件名存在的依據(jù)。將目錄項(xiàng)的0xB置為0F,其他就任由系統(tǒng)定義了,Windows9x或Windows 2000、XP通常支持不超過(guò)255個(gè)字符的長(zhǎng)文件名。系統(tǒng)將長(zhǎng)文件名以13個(gè)字符為單位進(jìn)行切割,每一組占據(jù)一個(gè)目錄項(xiàng)。所以可能一個(gè)文件需要多個(gè)目錄項(xiàng),這時(shí)長(zhǎng)文件名的各個(gè)目錄項(xiàng)按倒序排列在目錄表中,以防與其他文件名混淆。
長(zhǎng)文件名中的字符采用unicode形式編碼(一個(gè)巨大的進(jìn)步哦),每個(gè)字符占據(jù)2字節(jié)的空間。其目錄項(xiàng)定義如表15。
表15 FAT32長(zhǎng)文件目錄項(xiàng)32個(gè)字節(jié)的表示定義
字節(jié)偏移
(16進(jìn)制) 字節(jié)數(shù) 定義
0x0 1 屬性字節(jié)位意義 7 保留未用
6 1表示長(zhǎng)文件最后一個(gè)目錄項(xiàng)
5 保留未用
4 順序號(hào)數(shù)值
3
2
1
0
0x1~0xA 10 長(zhǎng)文件名unicode碼①
0xB 1 長(zhǎng)文件名目錄項(xiàng)標(biāo)志,取值0FH
0xC 1 系統(tǒng)保留
0xD 1 校驗(yàn)值(根據(jù)短文件名計(jì)算得出)
0xE~0x19 12 長(zhǎng)文件名unicode碼②
0x1A~0x1B 2 文件起始簇號(hào)(目前常置0)
0x1C~0x1F 4 長(zhǎng)文件名unicode碼③
系統(tǒng)在存儲(chǔ)長(zhǎng)文件名時(shí),總是先按倒序填充長(zhǎng)文件名目錄項(xiàng),然后緊跟其對(duì)應(yīng)的短文件名。從表15可以看出,長(zhǎng)文件名中并不存儲(chǔ)對(duì)應(yīng)文件的文件開(kāi)始簇、文件大小、各種時(shí)間和日期屬性。文件的這些屬性還是存放在短文件名目錄項(xiàng)中,一個(gè)長(zhǎng)文件名總是和其相應(yīng)的短文件名一一對(duì)應(yīng),短文件名沒(méi)有了長(zhǎng)文件名還可以讀,但長(zhǎng)文件名如果沒(méi)有對(duì)應(yīng)的短文件名,不管什么系統(tǒng)都將忽略其存在。所以短文件名是至關(guān)重要的。在不支持長(zhǎng)文件名的環(huán)境中對(duì)短文件名中的文件名和擴(kuò)展名字段作更改(包括刪除,因?yàn)閯h除是對(duì)首字符改寫(xiě)E5H),都會(huì)使長(zhǎng)文件名形同虛設(shè)。長(zhǎng)文件名和短文件名之間的聯(lián)系光靠他們之間的位置關(guān)系維系顯然遠(yuǎn)遠(yuǎn)不夠。其實(shí),長(zhǎng)文件名的0xD字節(jié)的校驗(yàn)和起很重要的作用,此校驗(yàn)和是用短文件名的11個(gè)字符通過(guò)一種運(yùn)算方式來(lái)得到的。系統(tǒng)根據(jù)相應(yīng)的算法來(lái)確定相應(yīng)的長(zhǎng)文件名和短文件名是否匹配。這個(gè)算法不太容易用公式說(shuō)明,我們用一段c程序來(lái)加以說(shuō)明。
假設(shè)文件名11個(gè)字符組成字符串shortname[],校驗(yàn)和用chknum表示。得到過(guò)程如下:
int i,j,chknum=0;
for (i=11; i>0; i--)
chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];
如果通過(guò)短文件名計(jì)算出來(lái)的校驗(yàn)和與長(zhǎng)文件名中的0xD偏移處數(shù)據(jù)不相等。系統(tǒng)無(wú)論如何都不會(huì)將它們配對(duì)的。依據(jù)長(zhǎng)文件名和短文件名對(duì)目錄項(xiàng)的定義,加上對(duì)簇的編號(hào)和鏈接,F(xiàn)AT32上數(shù)據(jù)的讀取便游刃有余了。