作者:zty,來源:www.,發(fā)布時(shí)間:13/05/14 一、硬盤的物理結(jié)構(gòu): 硬盤存儲(chǔ)數(shù)據(jù)是根據(jù)電、磁轉(zhuǎn)換原理實(shí)現(xiàn)的。硬盤由一個(gè)或幾個(gè)表面鍍有磁性物質(zhì)的金屬或玻璃等物質(zhì)盤片以及盤片兩面所安裝的磁頭和相應(yīng)的控制電路組成(圖1),其中盤片和磁頭密封在無(wú)塵的金屬殼中。 硬盤工作時(shí),盤片以設(shè)計(jì)轉(zhuǎn)速高速旋轉(zhuǎn),設(shè)置在盤片表面的磁頭則在電路控制下徑向移動(dòng)到指定位置然后將數(shù)據(jù)存儲(chǔ)或讀取出來。當(dāng)系統(tǒng)向硬盤寫入數(shù)據(jù)時(shí),磁頭中“寫數(shù)據(jù)”電流產(chǎn)生磁場(chǎng)使盤片表面磁性物質(zhì)狀態(tài)發(fā)生改變,并在寫電流磁場(chǎng)消失后仍能保持,這樣數(shù)據(jù)就存儲(chǔ)下來了;當(dāng)系統(tǒng)從硬盤中讀數(shù)據(jù)時(shí),磁頭經(jīng)過盤片指定區(qū)域,盤片表面磁場(chǎng)使磁頭產(chǎn)生感應(yīng)電流或線圈阻抗產(chǎn)生變化,經(jīng)相關(guān)電路處理后還原成數(shù)據(jù)。因此只要能將盤片表面處理得更平滑、磁頭設(shè)計(jì)得更精密以及盡量提高盤片旋轉(zhuǎn)速度,就能造出容量更大、讀寫數(shù)據(jù)速度更快的硬盤。這是因?yàn)楸P片表面處理越平、轉(zhuǎn)速越快就能越使磁頭離盤片表面越近,提高讀、寫靈敏度和速度;磁頭設(shè)計(jì)越小越精密就能使磁頭在盤片上占用空間越小,使磁頭在一張盤片上建立更多的磁道以存儲(chǔ)更多的數(shù)據(jù)。 二、硬盤的邏輯結(jié)構(gòu)。 硬盤由很多盤片(platter)組成,每個(gè)盤片的每個(gè)面都有一個(gè)讀寫磁頭。如果有N個(gè)盤片。就有2N個(gè)面,對(duì)應(yīng)2N個(gè)磁頭(Heads),從0、1、2開始編號(hào)。每個(gè)盤片被劃分成若干個(gè)同心圓磁道(邏輯上的,是不可見的。)每個(gè)盤片的劃分規(guī)則通常是一樣的。這樣每個(gè)盤片的半徑均為固定值R的同心圓再邏輯上形成了一個(gè)以電機(jī)主軸為軸的柱面(Cylinders),從外至里編號(hào)為0、1、2……每個(gè)盤片上的每個(gè)磁道又被劃分為幾十個(gè)扇區(qū)(Sector),通常的容量是512byte,并按照一定規(guī)則編號(hào)為1、2、3……形成Cylinders×Heads×Sector個(gè)扇區(qū)。這三個(gè)參數(shù)即是硬盤的物理參數(shù)。 三、磁盤引導(dǎo)原理。 3.1 MBR(master boot record)扇區(qū): 計(jì)算機(jī)在按下power鍵以后,開始執(zhí)行主板bios程序。進(jìn)行完一系列檢測(cè)和配置以后。開始按bios中設(shè)定的系統(tǒng)引導(dǎo)順序引導(dǎo)系統(tǒng)。假定現(xiàn)在是硬盤。Bios執(zhí)行完自己的程序后如何把執(zhí)行權(quán)交給硬盤呢。交給硬盤后又執(zhí)行存儲(chǔ)在哪里的程序呢。其實(shí),稱為mbr的一段代碼起著舉足輕重的作用。MBR(master boot record),即主引導(dǎo)記錄,有時(shí)也稱主引導(dǎo)扇區(qū)。位于整個(gè)硬盤的0柱面0磁頭1扇區(qū)(可以看作是硬盤的第一個(gè)扇區(qū)),bios在執(zhí)行自己固有的程序以后就會(huì)jump到mbr中的第一條指令。將系統(tǒng)的控制權(quán)交由mbr來執(zhí)行。在總共512byte的主引導(dǎo)記錄中,MBR的引導(dǎo)程序占了其中的前446個(gè)字節(jié)(偏移0H~偏移1BDH),隨后的64個(gè)字節(jié)(偏移1BEH~偏移1FDH)為DPT(Disk PartitionTable,硬盤分區(qū)表),最后的兩個(gè)字節(jié)“55 AA”(偏移1FEH~偏移1FFH)是分區(qū)有效結(jié)束標(biāo)志。 MBR不隨操作系統(tǒng)的不同而不同,意即不同的操作系統(tǒng)可能會(huì)存在相同的MBR,即使不同,MBR也不會(huì)夾帶操作系統(tǒng)的性質(zhì)。具有公共引導(dǎo)的特性。 下面是用winhex查看的一塊希捷120GB硬盤的mbr。 你的硬盤的MBR引導(dǎo)代碼可能并非這樣。不過即使不同,所執(zhí)行的功能大體是一樣的。這是wowocock關(guān)于磁盤mbr的反編譯,已加了詳細(xì)的注釋,感興趣可以細(xì)細(xì)研究一下。 操作系統(tǒng)為了便于用戶對(duì)磁盤的管理,加入了磁盤分區(qū)的概念。即將一塊磁盤邏輯劃分為幾塊。磁盤分區(qū)數(shù)目的多少只受限于C~Z的英文字母的數(shù)目,在上圖DPT共64個(gè)字節(jié)中如何表示多個(gè)分區(qū)的屬性呢?microsoft通過鏈接的方法解決了這個(gè)問題。在DPT共64個(gè)字節(jié)中,以16個(gè)字節(jié)為分區(qū)表項(xiàng)單位描述一個(gè)分區(qū)的屬性。也就是說,第一個(gè)分區(qū)表項(xiàng)描述一個(gè)分區(qū)的屬性,一般為基本分區(qū)。第二個(gè)分區(qū)表項(xiàng)描述除基本分區(qū)外的其余空間,一般而言,就是我們所說的擴(kuò)展分區(qū)。這部分的大體說明見表1。
注:上表中的超過1字節(jié)的數(shù)據(jù)都以實(shí)際數(shù)據(jù)顯示,就是按高位到地位的方式顯示。存儲(chǔ)時(shí)是按低位到高位存儲(chǔ)的。兩者表現(xiàn)不同,請(qǐng)仔細(xì)看清楚。以后出現(xiàn)的表,圖均同。 也可以在winhex中看到這些參數(shù)的意義: 說明:每個(gè)分區(qū)表項(xiàng)占用16個(gè)字節(jié),假定偏移地址從0開始。如圖3的分區(qū)表項(xiàng)3。分區(qū)表項(xiàng)4同分區(qū)表項(xiàng)3。 1、0H偏移為活動(dòng)分區(qū)是否標(biāo)志,只能選00H和80H。80H為活動(dòng),00H為非活動(dòng)。其余值對(duì)microsoft而言為非法值。 2、重新說明一下(這個(gè)非常重要):大于1個(gè)字節(jié)的數(shù)被以低字節(jié)在前的存儲(chǔ)格式格式(little endian format)或稱反字節(jié)順序保存下來。低字節(jié)在前的格式是一種保存數(shù)的方法,這樣,最低位的字節(jié)最先出現(xiàn)在十六進(jìn)制數(shù)符號(hào)中。例如,相對(duì)扇區(qū)數(shù)字段的值0x3F000000的低字節(jié)在前表示為0x0000003F。這個(gè)低字節(jié)在前的格式數(shù)的十進(jìn)制數(shù)為63。 3、系統(tǒng)在分區(qū)時(shí),各分區(qū)都不允許跨柱面,即均以柱面為單位,這就是通常所說的分區(qū)粒度。有時(shí)候我們分區(qū)是輸入分區(qū)的大小為7000M,分出來卻是6997M,就是這個(gè)原因。 偏移2H和偏移6H的扇區(qū)和柱面參數(shù)中,扇區(qū)占6位(bit),柱面占10位(bit),以偏移6H為例,其低6位用作扇區(qū)數(shù)的二進(jìn)制表示。其高兩位做柱面數(shù)10位中的高兩位,偏移7H組成的8位做柱面數(shù)10位中的低8位。由此可知,實(shí)際上用這種方式表示的分區(qū)容量是有限的,柱面和磁頭從0開始編號(hào),扇區(qū)從1開始編號(hào),所以最多只能表示1024個(gè)柱面×63個(gè)扇區(qū)×256個(gè)磁頭×512byte=8455716864byte。即通常的8.4GB(實(shí)際上應(yīng)該是7.8GB左右)限制。實(shí)際上磁頭數(shù)通常只用到255個(gè)(由匯編語(yǔ)言的尋址寄存器決定),即使把這3個(gè)字節(jié)按線性尋址,依然力不從心。 在后來的操作系統(tǒng)中,超過8.4GB的分區(qū)其實(shí)已經(jīng)不通過C/H/S的方式尋址了。而是通過偏移CH~偏移FH共4個(gè)字節(jié)32位線性扇區(qū)地址來表示分區(qū)所占用的扇區(qū)總數(shù)??芍ㄟ^4個(gè)字節(jié)可以表示2^32個(gè)扇區(qū),即2TB=2048GB,目前對(duì)于大多數(shù)計(jì)算機(jī)而言,這已經(jīng)是個(gè)天文數(shù)字了。在未超過8.4GB的分區(qū)上,C/H/S的表示方法和線性扇區(qū)的表示方法所表示的分區(qū)大小是一致的。也就是說,兩種表示方法是協(xié)調(diào)的。即使不協(xié)調(diào),也以線性尋址為準(zhǔn)。(可能在某些系統(tǒng)中會(huì)提示出錯(cuò))。超過8.4GB的分區(qū)結(jié)束C/H/S一般填充為FEH FFH FFH。即C/H/S所能表示的最大值。有時(shí)候也會(huì)用柱面對(duì)1024的模來填充。不過這幾個(gè)字節(jié)是什么其實(shí)都無(wú)關(guān)緊要了。 雖然現(xiàn)在的系統(tǒng)均采用線性尋址的方式來處理分區(qū)的大小。但不可跨柱面的原則依然沒變。本分區(qū)的扇區(qū)總數(shù)加上與前一分區(qū)之間的保留扇區(qū)數(shù)目依然必須是柱面容量的整數(shù)倍。(保留扇區(qū)中的第一個(gè)扇區(qū)就是存放分區(qū)表的MBR或虛擬MBR的扇區(qū),分區(qū)的扇區(qū)總數(shù)在線性表示方式上是不計(jì)入保留扇區(qū)的。如果是第一個(gè)分區(qū),保留扇區(qū)是本分區(qū)前的所有扇區(qū)。 附:分區(qū)表類型標(biāo)志如圖4 3.2 擴(kuò)展分區(qū): 擴(kuò)展分區(qū)中的每個(gè)邏輯驅(qū)動(dòng)器都存在一個(gè)類似于MBR的擴(kuò)展引導(dǎo)記錄( Extended Boot Record, EBR),也有人稱之為虛擬mbr或擴(kuò)展mbr,意思是一樣的。擴(kuò)展引導(dǎo)記錄包括一個(gè)擴(kuò)展分區(qū)表和該扇區(qū)的標(biāo)簽。擴(kuò)展引導(dǎo)記錄將記錄只包含擴(kuò)展分區(qū)中每個(gè)邏輯驅(qū)動(dòng)器的第一個(gè)柱面的第一面的信息。一個(gè)邏輯驅(qū)動(dòng)器中的引導(dǎo)扇區(qū)一般位于相對(duì)扇區(qū)32或63。但是,如果磁盤上沒有擴(kuò)展分區(qū),那么就不會(huì)有擴(kuò)展引導(dǎo)記錄和邏輯驅(qū)動(dòng)器。第一個(gè)邏輯驅(qū)動(dòng)器的擴(kuò)展分區(qū)表中的第一項(xiàng)指向它自身的引導(dǎo)扇區(qū)。第二項(xiàng)指向下一個(gè)邏輯驅(qū)動(dòng)器的EBR。如果不存在進(jìn)一步的邏輯驅(qū)動(dòng)器,第二項(xiàng)就不會(huì)使用,而且被記錄成一系列零。如果有附加的邏輯驅(qū)動(dòng)器,那么第二個(gè)邏輯驅(qū)動(dòng)器的擴(kuò)展分區(qū)表的第一項(xiàng)會(huì)指向它本身的引導(dǎo)扇區(qū)。第二個(gè)邏輯驅(qū)動(dòng)器的擴(kuò)展分區(qū)表的第二項(xiàng)指向下一個(gè)邏輯驅(qū)動(dòng)器的EBR。擴(kuò)展分區(qū)表的第三項(xiàng)和第四項(xiàng)永遠(yuǎn)都不會(huì)被使用。 通過一幅4分區(qū)的磁盤結(jié)構(gòu)圖可以看到磁盤的大致組織形式。如圖5: 關(guān)于擴(kuò)展分區(qū),如圖6所示,擴(kuò)展分區(qū)中邏輯驅(qū)動(dòng)器的擴(kuò)展引導(dǎo)記錄是一個(gè)連接表。該圖顯示了一個(gè)擴(kuò)展分區(qū)上的三個(gè)邏輯驅(qū)動(dòng)器,說明了前面的邏輯驅(qū)動(dòng)器和最后一個(gè)邏輯驅(qū)動(dòng)器之間在擴(kuò)展分區(qū)表中的差異。 除了擴(kuò)展分區(qū)上最后一個(gè)邏輯驅(qū)動(dòng)器外,表2中所描述的擴(kuò)展分區(qū)表的格式在每個(gè)邏輯驅(qū)動(dòng)器中都是重復(fù)的:第一個(gè)項(xiàng)標(biāo)識(shí)了邏輯驅(qū)動(dòng)器本身的引導(dǎo)扇區(qū),第二個(gè)項(xiàng)標(biāo)識(shí)了下一個(gè)邏輯驅(qū)動(dòng)器的EBR。最后一個(gè)邏輯驅(qū)動(dòng)器的擴(kuò)展分區(qū)表只會(huì)列出它本身的分區(qū)項(xiàng)。最后一個(gè)擴(kuò)展分區(qū)表的第二個(gè)項(xiàng)到第四個(gè)項(xiàng)被使用。 擴(kuò)展分區(qū)表項(xiàng)中的相對(duì)扇區(qū)數(shù)字段所顯示的是從擴(kuò)展分區(qū)開始到邏輯驅(qū)動(dòng)器中第一個(gè)扇區(qū)的位移的字節(jié)數(shù)??偵葏^(qū)數(shù)字段中的數(shù)是指組成該邏輯驅(qū)動(dòng)器的扇區(qū)數(shù)目??偵葏^(qū)數(shù)字段的值等于從擴(kuò)展分區(qū)表項(xiàng)所定義的引導(dǎo)扇區(qū)到邏輯驅(qū)動(dòng)器末尾的扇區(qū)數(shù)。 四、FAT分區(qū)原理。 先來一幅結(jié)構(gòu)圖: 現(xiàn)在我們著重研究FAT格式分區(qū)內(nèi)數(shù)據(jù)是如何存儲(chǔ)的。FAT分區(qū)格式是MICROSOFT最早支持的分區(qū)格式,依據(jù)FAT表中每個(gè)簇鏈的所占位數(shù)(有關(guān)概念,后面會(huì)講到)分為fat12、fat16、fat32三種格式“變種”,但其基本存儲(chǔ)方式是相似的。 仔細(xì)研究圖7中的fat16和fat32分區(qū)的組成結(jié)構(gòu)。下面依次解釋DBR、FAT1、FAT2、根目錄、數(shù)據(jù)區(qū)、剩余扇區(qū)的概念。提到的地址如無(wú)特別提示均為分區(qū)內(nèi)部偏移。 4.1 關(guān)于DBR. DBR區(qū)(DOS BOOT RECORD)即操作系統(tǒng)引導(dǎo)記錄區(qū)的意思,通常占用分區(qū)的第0扇區(qū)共512個(gè)字節(jié)(特殊情況也要占用其它保留扇區(qū),我們先說第0扇)。在這512個(gè)字節(jié)中,其實(shí)又是由跳轉(zhuǎn)指令,廠商標(biāo)志和操作系統(tǒng)版本號(hào),BPB(BIOS Parameter Block),擴(kuò)展BPB,os引導(dǎo)程序,結(jié)束標(biāo)志幾部分組成。 以用的最多的FAT32為例說明分區(qū)DBR各字節(jié)的含義。見圖8。 圖8的對(duì)應(yīng)解釋見表3
圖9給出了winhex對(duì)圖8 DBR的相關(guān)參數(shù)解釋: 根據(jù)上邊圖例,我們來討論DBR各字節(jié)的參數(shù)意義。 MBR將CPU執(zhí)行轉(zhuǎn)移給引導(dǎo)扇區(qū),因此,引導(dǎo)扇區(qū)的前三個(gè)字節(jié)必須是合法的可執(zhí)行的基于x86的CPU指令。這通常是一條跳轉(zhuǎn)指令,該指令負(fù)責(zé)跳過接下來的幾個(gè)不可執(zhí)行的字節(jié)(BPB和擴(kuò)展BPB),跳到操作系統(tǒng)引導(dǎo)代碼部分。 跳轉(zhuǎn)指令之后是8字節(jié)長(zhǎng)的OEM ID,它是一個(gè)字符串,OEM ID標(biāo)識(shí)了格式化該分區(qū)的操作系統(tǒng)的名稱和版本號(hào)。為了保留與MS-DOS的兼容性,通常Windows 2000格式化該盤是在FAT16和FAT32磁盤上的該字段中記錄了“MSDOS 5.0”,在NTFS磁盤上(關(guān)于ntfs,另述),Windows 2000記錄的是“NTFS”。通常在被Windows 95格式化的磁盤上OEM ID字段出現(xiàn)“MSWIN4.0”,在被Windows 95 OSR2和Windows 98格式化的磁盤上OEM ID字段出現(xiàn)“MSWIN4.1”。 接下來的從偏移0x0B開始的是一段描述能夠使可執(zhí)行引導(dǎo)代碼找到相關(guān)參數(shù)的信息。通常稱之為BPB(BIOS Parameter Block),BPB一般開始于相同的位移量,因此,標(biāo)準(zhǔn)的參數(shù)都處于一個(gè)已知的位置。磁盤容量和幾何結(jié)構(gòu)變量都被封在BPB之中。由于引導(dǎo)扇區(qū)的第一部分是一個(gè)x86跳轉(zhuǎn)指令。因此,將來通過在BPB末端附加新的信息,可以對(duì)BPB進(jìn)行擴(kuò)展。只需要對(duì)該跳轉(zhuǎn)指令作一個(gè)小的調(diào)整就可以適應(yīng)BPB的變化。圖9已經(jīng)列出了項(xiàng)目的名稱和取值,為了系統(tǒng)的研究,針對(duì)圖8,將FAT32分區(qū)格式的BPB含義和擴(kuò)展BPB含義釋義為表格,見表4和表5。
DBR的偏移0x5A開始的數(shù)據(jù)為操作系統(tǒng)引導(dǎo)代碼。這是由偏移0x00開始的跳轉(zhuǎn)指令所指向的。在圖8所列出的偏移0x00~0x02的跳轉(zhuǎn)指令“EB 58 90”清楚地指明了OS引導(dǎo)代碼的偏移位置。jump 58H加上跳轉(zhuǎn)指令所需的位移量,即開始于0x5A。此段指令在不同的操作系統(tǒng)上和不同的引導(dǎo)方式上,其內(nèi)容也是不同的。大多數(shù)的資料上都說win98,構(gòu)建于fat基本分區(qū)上的win2000,winxp所使用的DBR只占用基本分區(qū)的第0扇區(qū)。他們提到,對(duì)于fat32,一般的32個(gè)基本分區(qū)保留扇區(qū)只有第0扇區(qū)是有用的。實(shí)際上,以FAT32構(gòu)建的操作系統(tǒng)如果是win98,系統(tǒng)會(huì)使用基本分區(qū)的第0扇區(qū)和第2扇區(qū)存儲(chǔ)os引導(dǎo)代碼;以FAT32構(gòu)建的操作系統(tǒng)如果是win2000或winxp,系統(tǒng)會(huì)使用基本分區(qū)的第0扇區(qū)和第0xC扇區(qū)(win2000或winxp,其第0xC的位置由第0扇區(qū)的0xAB偏移指出)存儲(chǔ)os引導(dǎo)代碼。所以,在fat32分區(qū)格式上,如果DBR一扇區(qū)的內(nèi)容正確而缺少第2扇區(qū)(win98系統(tǒng))或第0xC扇區(qū)(win2000或winxp系統(tǒng)),系統(tǒng)也是無(wú)法啟動(dòng)的。如果自己手動(dòng)設(shè)置NTLDR雙系統(tǒng),必須知道這一點(diǎn)。 DBR扇區(qū)的最后兩個(gè)字節(jié)一般存儲(chǔ)值為0x55AA的DBR有效標(biāo)志,對(duì)于其他的取值,系統(tǒng)將不會(huì)執(zhí)行DBR相關(guān)指令。上面提到的其他幾個(gè)參與os引導(dǎo)的扇區(qū)也需以0x55AA為合法結(jié)束標(biāo)志。 FAT16 DBR: FAT32中DBR的含義大致如此,對(duì)于FAT12和FAT16其基本意義類似,只是相關(guān)偏移量和參數(shù)意義有小的差異,F(xiàn)AT格式的區(qū)別和來因,以后會(huì)說到,此處不在多說FAT12與FAT16。我將FAT16的扇區(qū)參數(shù)意義列表。感興趣的朋友自己研究一下,和FAT32大同小異的。
4.2 關(guān)于保留扇區(qū) 在上述FAT文件系統(tǒng)DBR的偏移0x0E處,用2個(gè)字節(jié)存儲(chǔ)保留扇區(qū)的數(shù)目。所謂保留扇區(qū)(有時(shí)候會(huì)叫系統(tǒng)扇區(qū),隱藏扇區(qū)),是指從分區(qū)DBR扇區(qū)開始的僅為系統(tǒng)所有的扇區(qū),包括DBR扇區(qū)。在FAT16文件系統(tǒng)中,保留扇區(qū)的數(shù)據(jù)通常設(shè)置為1,即僅僅DBR扇區(qū)。而在FAT32中,保留扇區(qū)的數(shù)據(jù)通常取為32,有時(shí)候用Partition Magic分過的FAT32分區(qū)會(huì)設(shè)置36個(gè)保留扇區(qū),有的工具可能會(huì)設(shè)置63個(gè)保留扇區(qū)。 FAT32中的保留扇區(qū)除了磁盤總第0扇區(qū)用作DBR,總第2扇區(qū)(win98系統(tǒng))或總第0xC扇區(qū)(win2000,winxp)用作OS引導(dǎo)代碼擴(kuò)展部分外,其余扇區(qū)都不參與操作系統(tǒng)管理與磁盤數(shù)據(jù)管理,通常情況下是沒作用的。操作系統(tǒng)之所以在FAT32中設(shè)置保留扇區(qū),是為了對(duì)DBR作備份或留待以后升級(jí)時(shí)用。FAT32中,DBR偏移0x34占2字節(jié)的數(shù)據(jù)指明了DBR備份扇區(qū)所在,一般為0x06,即第6扇區(qū)。當(dāng)FAT32分區(qū)DBR扇區(qū)被破壞導(dǎo)致分區(qū)無(wú)法訪問時(shí)??梢杂玫?扇區(qū)的原備份替換第0扇區(qū)來找回?cái)?shù)據(jù)。 4.3 FAT表和數(shù)據(jù)的存儲(chǔ)原則。 FAT表(File Allocation Table 文件分配表),是Microsoft在FAT文件系統(tǒng)中用于磁盤數(shù)據(jù)(文件)索引和定位引進(jìn)的一種鏈?zhǔn)浇Y(jié)構(gòu)。假如把磁盤比作一本書,F(xiàn)AT表可以認(rèn)為相當(dāng)于書中的目錄,而文件就是各個(gè)章節(jié)的內(nèi)容。但FAT表的表示方法卻與目錄有很大的不同。 在FAT文件系統(tǒng)中,文件的存儲(chǔ)依照FAT表制定的簇鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)來進(jìn)行。同時(shí),F(xiàn)AT文件系統(tǒng)將組織數(shù)據(jù)時(shí)使用的目錄也抽象為文件,以簡(jiǎn)化對(duì)數(shù)據(jù)的管理。 ★存儲(chǔ)過程假想: 我們模擬對(duì)一個(gè)分區(qū)存儲(chǔ)數(shù)據(jù)的過程來說明FAT文件系統(tǒng)中數(shù)據(jù)的存儲(chǔ)原則。 假定現(xiàn)在有一個(gè)空的完全沒有存放數(shù)據(jù)的磁盤,大小為100KB,我們將其想象為線形的空間地址。為了存儲(chǔ)管理上的便利,我們?nèi)藶榈膶⑦@100KB的空間均分成100份,每份1KB。我們來依次存儲(chǔ)這樣幾個(gè)文件:A.TXT(大小10KB),B.TXT(大小53.6KB),C.TXT(大小20.5KB)。 最起碼能夠想到,我們可以順序的在這100KB空間中存放這3個(gè)文件。同時(shí)不要忘了,我們還要記下他們的大小和開始的位置,這樣下次要用時(shí)才能找的到,這就像是目錄。為了便于查找,我們假定用第1K的空間來存儲(chǔ)他們的特征(屬性)。還有,我們?cè)O(shè)計(jì)的存儲(chǔ)單位是1KB,所以,A.TXT我們需要10個(gè)存儲(chǔ)單位(為了說明方便,我們把存儲(chǔ)單位叫做“簇”吧。也能少打點(diǎn)字,呵呵。),B.TXT需要54個(gè)簇,C.TXT需要21個(gè)簇??赡苡腥藭?huì)說B.TXT和C.TXT不是各自浪費(fèi)了不到1簇的空間嗎?干嘛不讓他們緊挨著,不是省地方嗎?我的回答是,如果按照這樣的方式存儲(chǔ),目錄中原本只需要記下簇號(hào),現(xiàn)在還需要記下簇內(nèi)的偏移,這樣會(huì)增加目錄的存儲(chǔ)量,而且存取沒有了規(guī)則,讀取也不太方便,是得不償失的。 根據(jù)上面所說的思想,我們?cè)O(shè)計(jì)了這樣的圖4.3.1所示的存儲(chǔ)方式。 ![]() 我們?cè)倏紤]如何來寫這三個(gè)文件的目錄。對(duì)于每個(gè)文件而言,一定要記錄的有:文件名,開始簇,大小,創(chuàng)建日期、時(shí)間,修改日期、時(shí)間,文件的讀寫屬性等。這里大小能不能用結(jié)束簇來計(jì)算呢?一定不能,因?yàn)槲募拇笮〔灰欢ň褪钦麛?shù)個(gè)簇的大小,否則的話像B.TXT的內(nèi)容就是54KB的內(nèi)容了,少了固然不行,可多了也是不行的。那么我們?cè)趺从涗浤兀靠梢韵胂笠幌?。為了管理上的方便,我們用?shù)據(jù)庫(kù)的管理方式來管理我們的目錄。于是我把1KB再分成10份,假定開始簇號(hào)為0,定義每份100B的各個(gè)位置的代表含義如圖4.3.2 這樣設(shè)計(jì)的結(jié)構(gòu)絕對(duì)可以對(duì)文件進(jìn)行正確的讀寫了。接著讓我們?cè)O(shè)計(jì)的文件系統(tǒng)工作吧。先改動(dòng)個(gè)文件,比如A.TXT,增加點(diǎn)內(nèi)容吧!咦?增加后往哪里放呀,雖然存儲(chǔ)塊的后面有很多空間,但緊隨其后B.TXT的數(shù)據(jù)還頂著呢?要是把A.TXT移到后邊太浪費(fèi)處理資源,而且也不一定解決問題。這個(gè)問題看來暫時(shí)解決不了。 那我們換個(gè)操作,把B.txt刪了,b.txt的空間隨之釋放。這時(shí)候空間如圖4.3.3,目錄如圖4.3.4 這個(gè)操作看來還可以,我們接著做,在存入一個(gè)文件D.txt(大小為60.3KB),總共100簇的空間只用了31簇,還有68簇剩余,按說能放下??墒??往那里放呢?沒有61個(gè)連續(xù)的空間了,目錄行沒辦法寫了,看來無(wú)連續(xù)塊存儲(chǔ)暫時(shí)也不行。 你一定能夠想到我們可以在連續(xù)空間不夠或增加文件長(zhǎng)度的時(shí)候轉(zhuǎn)移影響我們操作的其他文件,從而騰出空間來,但我要問你,那不是成天啥也不要干了,就是倒騰東西了嗎? 看來我們?cè)O(shè)計(jì)的文件系統(tǒng)有致命的漏洞,怎么解決呢?。。。。。。。。。。 其實(shí)可以這樣解決: 首先我們?cè)试S文件的不連續(xù)存儲(chǔ)。目錄中依然只記錄開始簇和文件的大小。那么我們?cè)趺从涗浳募加媚切┐啬?,以文件映射簇不太方便,因?yàn)槲募遣还潭ǖ?。我們換個(gè)思想,可以用簇來映射文件,在整個(gè)存儲(chǔ)空間的前部留下幾簇來記錄數(shù)據(jù)區(qū)中數(shù)據(jù)與簇號(hào)的關(guān)系。對(duì)于上例因?yàn)榭偪臻g也不大,所以用前部的1Kb的空間來記錄這種對(duì)應(yīng),假設(shè)3個(gè)文件都存儲(chǔ),空間分配如圖4.3.5,同時(shí)修改一下目錄,如圖4.3.6 第一簇用來記錄數(shù)據(jù)區(qū)中每一簇的被占用情況,暫時(shí)稱其為文件分配表。結(jié)合文件分配表和文件目錄就可以達(dá)到完全的文件讀取了。我們想到,把文件分配表做成一個(gè)數(shù)據(jù)表,以圖4.3.7的形式記錄簇與數(shù)據(jù)的對(duì)應(yīng)。 用圖4.3.7的組織方式是完全可以實(shí)現(xiàn)對(duì)文件占有簇的記錄的。但還不夠效率。比如文件名在文件分配表中記錄太多,浪費(fèi)空間,而實(shí)際上在目錄中已經(jīng)記錄了文件的開始簇了。所以可以改良一下,用鏈的方式來存放占有簇的關(guān)系,變成圖4.3.8的組織方式。 參照?qǐng)D4.3.8來理解一下文件分配表的意義。如文件a.txt我們根據(jù)目錄項(xiàng)中指定的a.txt的首簇為2,然后找到文件分配表的第2簇記錄,上面登記的是3,我們就能確定下一簇是3。找到文件分配表的第3簇記錄,上面登記的是4,我們就能確定下一簇是4......直到指到第11簇,發(fā)現(xiàn)下一個(gè)指向是FF,就是結(jié)束。文件便絲毫無(wú)誤讀取完畢。 我們?cè)倏瓷厦嫣岬降牡谌N情況,就是將b.txt刪除以后,存入一個(gè)大小為60.3KB的d.txt。利用簇鏈可以很容易的實(shí)現(xiàn)。實(shí)現(xiàn)后的磁盤如圖4.3.9 4.3.10 ; 4.3.11 ★FAT16存儲(chǔ)原理: 當(dāng)把一部分磁盤空間格式化為fat文件系統(tǒng)時(shí),fat文件系統(tǒng)就將這個(gè)分區(qū)當(dāng)成整塊可分配的區(qū)域進(jìn)行規(guī)劃,以便于數(shù)據(jù)的存儲(chǔ)。一般來講,其劃分形式如圖7所示。我們把FAT16部分提取出來,詳細(xì)描述一下: FAT16是Microsoft較早推出的文件系統(tǒng),具有高度兼容性,目前仍然廣泛應(yīng)用于個(gè)人電腦尤其是移動(dòng)存儲(chǔ)設(shè)備中,F(xiàn)AT16簡(jiǎn)單來講由圖4.3.11所示的6部分組成(主要是前5部分)。引導(dǎo)扇區(qū)(DBR)我們已經(jīng)說過,FAT16在DBR之后沒有留有任何保留扇區(qū),其后緊隨的便是FAT表。FAT表是FAT16用來記錄磁盤數(shù)據(jù)區(qū)簇鏈結(jié)構(gòu)的。像前面我們說過的例子一樣,F(xiàn)AT將磁盤空間按一定數(shù)目的扇區(qū)為單位進(jìn)行劃分,這樣的單位稱為簇。通常情況下,每扇區(qū)512字節(jié)的原則是不變的。簇的大小一般是2n(n為整數(shù))個(gè)扇區(qū)的大小,像512B,1K,2K,4K,8K,16K,32K,64K。實(shí)際中通常不超過32K。 之所以簇為單位而不以扇區(qū)為單位進(jìn)行磁盤的分配,是因?yàn)楫?dāng)分區(qū)容量較大時(shí),采用大小為512b的扇區(qū)管理會(huì)增加fat表的項(xiàng)數(shù),對(duì)大文件存取增加消耗,文件系統(tǒng)效率不高。分區(qū)的大小和簇的取值是有關(guān)系的,見表9。
注意:少于32680個(gè)扇區(qū)的分區(qū)中,簇空間大小可最多達(dá)到每個(gè)簇8個(gè)扇區(qū)。不管用戶是使用磁盤管理器來格式化分區(qū),還是使用命令提示行鍵入format命令格式化,格式化程序都創(chuàng)建一個(gè)12位的FAT。少于16MB的分區(qū),系統(tǒng)通常會(huì)將其格式化成12位的FAT,F(xiàn)AT12是FAT的初始實(shí)現(xiàn)形式,是針對(duì)小型介質(zhì)的。FAT12文件分配表要比FAT16和FAT32的文件分配表小,因?yàn)樗鼘?duì)每個(gè)條目使用的空間較少。這就給數(shù)據(jù)留下較多的空間。所有用FAT12格式化的5.25英寸軟盤以及1.44MB的3.5英寸軟盤都是由FAT12格式化的。除了FAT表中記錄每簇鏈結(jié)的二進(jìn)制位數(shù)與FAT16不同外,其余原理與FAT16均相同,不再單獨(dú)解釋。。。 格式化FAT16分區(qū)時(shí),格式化程序根據(jù)分區(qū)的大小確定簇的大小,然后根據(jù)保留扇區(qū)的數(shù)目、根目錄的扇區(qū)數(shù)目、數(shù)據(jù)區(qū)可分的簇?cái)?shù)與FAT表本身所占空間來確定FAT表所需的扇區(qū)數(shù)目,然后將計(jì)算后的結(jié)果寫入DBR的相關(guān)位置。 FAT16 DBR參數(shù)的偏移0x11處記錄了根目錄所占扇區(qū)的數(shù)目。偏移0x16記錄了FAT表所占扇區(qū)的數(shù)據(jù)。偏移0x10記錄了FAT表的副本數(shù)目。系統(tǒng)在得到這幾項(xiàng)參數(shù)以后,就可以確定數(shù)據(jù)區(qū)的開始扇區(qū)偏移了。 FAT16文件系統(tǒng)從根目錄所占的32個(gè)扇區(qū)之后的第一個(gè)扇區(qū)開始以簇為單位進(jìn)行數(shù)據(jù)的處理,這之前仍以扇區(qū)為單位。對(duì)于根目錄之后的第一個(gè)簇,系統(tǒng)并不編號(hào)為第0簇或第1簇 (可能是留作關(guān)鍵字的原因吧),而是編號(hào)為第2簇,也就是說數(shù)據(jù)區(qū)順序上的第1個(gè)簇也是編號(hào)上的第2簇。 FAT文件系統(tǒng)之所以有12,16,32不同的版本之分,其根本在于FAT表用來記錄任意一簇鏈接的二進(jìn)制位數(shù)。以FAT16為例,每一簇在FAT表中占據(jù)2字節(jié)(二進(jìn)制16位)。所以,F(xiàn)AT16最大可以表示的簇號(hào)為0xFFFF(十進(jìn)制的65535),以32K為簇的大小的話,F(xiàn)AT32可以管理的最大磁盤空間為:32KB×65535=2048MB,這就是為什么FAT16不支持超過2GB分區(qū)的原因。 FAT表實(shí)際上是一個(gè)數(shù)據(jù)表,以2個(gè)字節(jié)為單位,我們暫將這個(gè)單位稱為FAT記錄項(xiàng),通常情況其第1、2個(gè)記錄項(xiàng)(前4個(gè)字節(jié))用作介質(zhì)描述。從第三個(gè)記錄項(xiàng)開始記錄除根目錄外的其他文件及文件夾的簇鏈情況。根據(jù)簇的表現(xiàn)情況FAT用相應(yīng)的取值來描述,見表10
看一幅在winhex所截FAT16的文件分配表,圖10: 如圖,F(xiàn)AT表以"F8 FF FF FF" 開頭,此2字節(jié)為介質(zhì)描述單元,并不參與FAT表簇鏈關(guān)系。小紅字標(biāo)出的是FAT扇區(qū)每2字節(jié)對(duì)應(yīng)的簇號(hào)。 相對(duì)偏移0x4~0x5偏移為第2簇(順序上第1簇),此處為FF,表示存儲(chǔ)在第2簇上的文件(目錄)是個(gè)小文件,只占用1個(gè)簇便結(jié)束了。 第3簇中存放的數(shù)據(jù)是0x0005,這是一個(gè)文件或文件夾的首簇。其內(nèi)容為第5簇,就是說接下來的簇位于第5簇——〉 FAT表指引我們到達(dá)FAT表的第5簇指向,上面寫的數(shù)據(jù)是“FF FF”,意即此文件已至尾簇。 第4簇中存放的數(shù)據(jù)是0x0006,這又是一個(gè)文件或文件夾的首簇。其內(nèi)容為第6簇,就是說接下來的簇位于第6簇——〉FAT表指引我們到達(dá)FAT表的第6簇指向,上面寫的數(shù)據(jù)是0x0007,就是說接下來的簇位于第7簇——〉FAT表指引我們到達(dá)FAT表的第7簇指向……直到根據(jù)FAT鏈讀取到扇區(qū)相對(duì)偏移0x1A~0x1B,也就是第13簇,上面寫的數(shù)據(jù)是0x000E,也就是指向第14簇——〉14簇的內(nèi)容為"FF FF",意即此文件已至尾簇。 后面的FAT表數(shù)據(jù)與上面的道理相同。不再分析。 FAT表記錄了磁盤數(shù)據(jù)文件的存儲(chǔ)鏈表,對(duì)于數(shù)據(jù)的讀取而言是極其重要的,以至于Microsoft為其開發(fā)的FAT文件系統(tǒng)中的FAT表創(chuàng)建了一份備份,就是我們看到的FAT2。FAT2與FAT1的內(nèi)容通常是即時(shí)同步的,也就是說如果通過正常的系統(tǒng)讀寫對(duì)FAT1做了更改,那么FAT2也同樣被更新。如果從這個(gè)角度來看,系統(tǒng)的這個(gè)功能在數(shù)據(jù)恢復(fù)時(shí)是個(gè)天災(zāi)。 FAT文件系統(tǒng)的目錄結(jié)構(gòu)其實(shí)是一顆有向的從根到葉的樹,這里提到的有向是指對(duì)于FAT分區(qū)內(nèi)的任一文件(包括文件夾),均需從根目錄尋址來找到??梢赃@樣認(rèn)為:目錄存儲(chǔ)結(jié)構(gòu)的入口就是根目錄。 FAT文件系統(tǒng)根據(jù)根目錄來尋址其他文件(包括文件夾),故而根目錄的位置必須在磁盤存取數(shù)據(jù)之前得以確定。FAT文件系統(tǒng)就是根據(jù)分區(qū)的相關(guān)DBR參數(shù)與DBR中存放的已經(jīng)計(jì)算好的FAT表(2份)的大小來確定的。格式化以后,跟目錄的大小和位置其實(shí)都已經(jīng)確定下來了:位置緊隨FAT2之后,大小通常為32個(gè)扇區(qū)。根目錄之后便是數(shù)據(jù)區(qū)第2簇。 FAT文件系統(tǒng)的一個(gè)重要思想是把目錄(文件夾)當(dāng)作一個(gè)特殊的文件來處理,F(xiàn)AT32甚至將根目錄當(dāng)作文件處理(旁:NTFS將分區(qū)參數(shù)、安全權(quán)限等好多東西抽象為文件更是這個(gè)思想的升華),在FAT16中,雖然根目錄地位并不等同于普通的文件或者說是目錄,但其組織形式和普通的目錄(文件夾)并沒有不同。FAT分區(qū)中所有的文件夾(目錄)文件,實(shí)際上可以看作是一個(gè)存放其他文件(文件夾)入口參數(shù)的數(shù)據(jù)表。所以目錄的占用空間的大小并不等同于其下所有數(shù)據(jù)的大小,但也不等同于0。通常是占很小的空間的,可以看作目錄文件是一個(gè)簡(jiǎn)單的二維表文件。其具體存儲(chǔ)原理是: 不管目錄文件所占空間為多少簇,一簇為多少字節(jié)。系統(tǒng)都會(huì)以32個(gè)字節(jié)為單位進(jìn)行目錄文件所占簇的分配。這32個(gè)字節(jié)以確定的偏移來定義本目錄下的一個(gè)文件(或文件夾)的屬性,實(shí)際上是一個(gè)簡(jiǎn)單的二維表。 這32個(gè)字節(jié)的各字節(jié)偏移定義如表11:
對(duì)圖10中的一些取值進(jìn)行說明: (1)、對(duì)于短文件名,系統(tǒng)將文件名分成兩部分進(jìn)行存儲(chǔ),即主文件名+擴(kuò)展名。0x0~0x7字節(jié)記錄文件的主文件名,0x8~0xA記錄文件的擴(kuò)展名,取文件名中的ASCII碼值。不記錄主文件名與擴(kuò)展名之間的"." 主文件名不足8個(gè)字符以空白符(20H)填充,擴(kuò)展名不足3個(gè)字符同樣以空白符(20H)填充。0x0偏移處的取值若為00H,表明目錄項(xiàng)為空;若為E5H,表明目錄項(xiàng)曾被使用,但對(duì)應(yīng)的文件或文件夾已被刪除。(這也是誤刪除后恢復(fù)的理論依據(jù))。文件名中的第一個(gè)字符若為“.”或“..”表示這個(gè)簇記錄的是一個(gè)子目錄的目錄項(xiàng)?!?”代表當(dāng)前目錄;“..”代表上級(jí)目錄(和我們?cè)赿os或windows中的使用意思是一樣的,如果磁盤數(shù)據(jù)被破壞,就可以通過這兩個(gè)目錄項(xiàng)的具體參數(shù)推算磁盤的數(shù)據(jù)區(qū)的起始位置,猜測(cè)簇的大小等等,故而是比較重要的) (2)、0xB的屬性字段:可以看作系統(tǒng)將0xB的一個(gè)字節(jié)分成8位,用其中的一位代表某種屬性的有或無(wú)。這樣,一個(gè)字節(jié)中的8位每位取不同的值就能反映各個(gè)屬性的不同取值了。如00000101就表示這是個(gè)文件,屬性是只讀、系統(tǒng)。 (3)、0xC~0x15在原FAT16的定義中是保留未用的。在高版本的WINDOWS系統(tǒng)中有時(shí)也用它來記錄修改時(shí)間和最近訪問時(shí)間。那樣其字段的意義和FAT32的定義是相同的,見后邊FAT32。 (4)、0x16~0x17中的時(shí)間=小時(shí)*2048+分鐘*32+秒/2。得出的結(jié)果換算成16進(jìn)制填入即可。也就是:0x16字節(jié)的0~4位是以2秒為單位的量值;0x16字節(jié)的5~7位和0x17字節(jié)的0~2位是分鐘;0x17字節(jié)的3~7位是小時(shí)。 (5)、0x18~0x19中的日期=(年份-1980)*512+月份*32+日。得出的結(jié)果換算成16進(jìn)制填入即可。也就是:0x18字節(jié)0~4位是日期數(shù);0x18字節(jié)5~7位和0x19字節(jié)0位是月份;0x19字節(jié)的1~7位為年號(hào),原定義中0~119分別代表1980~2099,目前高版本的Windows允許取0~127,即年號(hào)最大可以到2107年。 (6)、0x1A~0x1B存放文件或目錄的表示文件的首簇號(hào),系統(tǒng)根據(jù)掌握的首簇號(hào)在FAT表中找到入口,然后再跟蹤簇鏈直至簇尾,同時(shí)用0x1C~0x1F處字節(jié)判定有效性。就可以完全無(wú)誤的讀取文件(目錄)了。 (7)、普通子目錄的尋址過程也是通過其父目錄中的目錄項(xiàng)來指定的,與數(shù)據(jù)文件(指非目錄文件)不同的是目錄項(xiàng)偏移0xB的第4位置1,而數(shù)據(jù)文件為0。 對(duì)于整個(gè)FAT分區(qū)而言,簇的分配并不完全總是分配干凈的。如一個(gè)數(shù)據(jù)區(qū)為99個(gè)扇區(qū)的FAT系統(tǒng),如果簇的大小設(shè)定為2扇區(qū),就會(huì)有1個(gè)扇區(qū)無(wú)法分配給任何一個(gè)簇。這就是分區(qū)的剩余扇區(qū),位于分區(qū)的末尾。有的系統(tǒng)用最后一個(gè)剩余扇區(qū)備份本分區(qū)的DBR,這也是一種好的備份方法。 早的FAT16系統(tǒng)并沒有長(zhǎng)文件名一說,Windows操作系統(tǒng)已經(jīng)完全支持在FAT16上的長(zhǎng)文件名了。FAT16的長(zhǎng)文件名與FAT32長(zhǎng)文件名的定義是相同的,關(guān)于長(zhǎng)文件名,在FAT32部分再詳細(xì)作解釋。 ★FAT32存儲(chǔ)原理: FAT32是個(gè)非常有功勞的文件系統(tǒng),Microsoft成功地設(shè)計(jì)并運(yùn)用了它,直到今天NTFS鋪天蓋地襲來的時(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)成。
FAT32在格式化的過程中就根據(jù)分區(qū)的特點(diǎn)構(gòu)建好了它的DBR,其中BPB參數(shù)是很重要的,可以回過頭來看一下表4和表5。首先FAT32保留扇區(qū)的數(shù)目默認(rèn)為32個(gè),而不是FAT16的僅僅一個(gè)。這樣的好處是有助于磁盤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遭到意外破壞時(shí)恢復(fù)DBR。 FAT32的文件分配表的數(shù)據(jù)結(jié)構(gòu)依然和FAT16相同,所不同的是,F(xiàn)AT32將記錄簇鏈的二進(jìn)制位數(shù)擴(kuò)展到了32位,故而這種文件系統(tǒ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í)際中通常不格式化超過32GB的FAT32分區(qū)。WIN2000及之上的OS已經(jīng)不直接支持對(duì)超過32GB的分區(qū)格式化成FAT32,但WIN98依然可以格式化大到127GB的FAT32分區(qū),但這樣沒必要也不推薦。同時(shí)FAT32也有小的限制,F(xiàn)AT32卷必須至少有65527個(gè)簇,所以對(duì)于小的分區(qū),仍然需要使用FAT16或FAT12。 分區(qū)變大時(shí),如果簇很小,文件分配表也隨之變大。仍然會(huì)有上面的效率問題存在。既要有效地讀寫大文件,又要最大可能的減少空間的浪費(fèi)。FAT32同樣規(guī)定了相應(yīng)的分區(qū)空間對(duì)應(yīng)的簇的大小,見表12:
簇的取值意義和FAT16類似,不過是位數(shù)長(zhǎng)了點(diǎn)罷了,比較見表13:
FAT32的另一項(xiàng)重大改革是根目錄的文件化,即將根目錄等同于普通的文件。這樣根目錄便沒有了FAT16中512個(gè)目錄項(xiàng)的限制,不夠用的時(shí)候增加簇鏈,分配空簇即可。而且,根目錄的位置也不再硬性地固定了,可以存儲(chǔ)在分區(qū)內(nèi)可尋址的任意簇內(nèi),不過通常根目錄是最早建立的(格式化就生成了)目錄表。所以,我們看到的情況基本上都是根目錄首簇占簇區(qū)順序上的第1個(gè)簇。在圖4.3.12中也是按這種情況制作的畫的。 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ù)意義見表14:
* 此字段在短文件目錄項(xiàng)中不可取值0FH,如果設(shè)值為0FH,目錄段為長(zhǎng)文件名目錄段 說明: (1)、這是FAT32短文件格式目錄項(xiàng)的意義。其中文件名、擴(kuò)展名、時(shí)間、日期的算法和FAT16時(shí)相同的。 (2)、由于FAT32可尋址的簇號(hào)到了32位二進(jìn)制數(shù)。所以系統(tǒng)在記錄文件(文件夾)開始簇地址的時(shí)候也需要32位來記錄,F(xiàn)AT32啟用目錄項(xiàng)偏移0x12~0x13來表示起始簇號(hào)的高16位。 (3)、文件長(zhǎng)度依然用4個(gè)字節(jié)表示,這說明FAT32依然只支持小于4GB的文件(目錄),超過4GB的文件(目錄),系統(tǒng)會(huì)截?cái)嗵幚怼?/p> 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)來記錄和編輯,并隱藏起短文件名。 當(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è)字母。通過數(shù)學(xué)操縱長(zhǎng)文件名的剩余字母生成短文件名的后四個(gè)字母,然后加后綴"~1"直到最后(如果有必要,或是其他數(shù)字以避免重復(fù)的文件名)。 (4)、如果存在老OS或程序無(wú)法讀取的字符,換以"_" 長(zhǎng)文件名的實(shí)現(xiàn)有賴于目錄項(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通常支持不超過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。
系統(tǒng)在存儲(chǔ)長(zhǎng)文件名時(shí),總是先按倒序填充長(zhǎng)文件名目錄項(xiàng),然后緊跟其對(duì)應(yīng)的短文件名。從表15可以看出,長(zhǎng)文件名中并不存儲(chǔ)對(duì)應(yīng)文件的文件開始簇、文件大小、各種時(shí)間和日期屬性。文件的這些屬性還是存放在短文件名目錄項(xiàng)中,一個(gè)長(zhǎng)文件名總是和其相應(yīng)的短文件名一一對(duì)應(yīng),短文件名沒有了長(zhǎng)文件名還可以讀,但長(zhǎng)文件名如果沒有對(duì)應(yīng)的短文件名,不管什么系統(tǒng)都將忽略其存在。所以短文件名是至關(guān)重要的。在不支持長(zhǎng)文件名的環(huán)境中對(duì)短文件名中的文件名和擴(kuò)展名字段作更改(包括刪除,因?yàn)閯h除是對(duì)首字符改寫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è)字符通過一種運(yùn)算方式來得到的。系統(tǒng)根據(jù)相應(yīng)的算法來確定相應(yīng)的長(zhǎng)文件名和短文件名是否匹配。這個(gè)算法不太容易用公式說明,我們用一段c程序來加以說明。 假設(shè)文件名11個(gè)字符組成字符串shortname[],校驗(yàn)和用chknum表示。得到過程如下: int i,j,chknum=0; for (i=11; i>0; i--) chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; 如果通過短文件名計(jì)算出來的校驗(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ù)的讀取便游刃有余了。 FAT32文件系統(tǒng)學(xué)習(xí)目的:需要編寫SD讀圖片的底層驅(qū)動(dòng)程序。所以要了解一個(gè)SD卡常用文件系統(tǒng)基本概念。累計(jì)學(xué)習(xí)用時(shí)2.5小時(shí)。 一,F(xiàn)AT32的保留區(qū) 1,引導(dǎo)扇區(qū) :引導(dǎo)扇區(qū)是FAT32文件系統(tǒng)的第一個(gè)扇區(qū),也稱為DBR扇區(qū)。它包含這樣一些文件系統(tǒng)的基本信息: 【1】 每扇區(qū)字節(jié)數(shù) 【2】 每簇扇區(qū)數(shù) 【3】 保留扇區(qū)數(shù)【4】 FAT表個(gè)數(shù) 【5】 文件系統(tǒng)大?。ㄉ葏^(qū)數(shù))【6】 每個(gè)FAT表大?。ㄉ葏^(qū)數(shù)) 【7】 根目錄起始簇號(hào) 【8】 其他一些附加信息 邊看說明,邊看圖片不太方便,我就按照說明內(nèi)容,把說明直接標(biāo)注在圖片上了。 我的SD卡是手機(jī)里的tf卡+sd卡套。之前沒有問題。當(dāng)我第一次格式化后,就發(fā)現(xiàn)不正常了。雖然存取文件都沒問題。但是放在我的開發(fā)板上測(cè)試SD的時(shí)候,數(shù)據(jù)顯示不正確。 現(xiàn)在我初步發(fā)現(xiàn)問題在這里 【13】0x1C~0x1F:4個(gè)字節(jié),分區(qū)前已使用扇區(qū)數(shù),137(0x00 00 00 89)。(這個(gè)數(shù)據(jù)要尤其的重視,文件系統(tǒng)初始化的第一步要找的就是這玩意兒。因?yàn)槲覀兊腟D卡沒有分區(qū),默認(rèn)就是一個(gè)分區(qū),這個(gè)數(shù)據(jù)就是相對(duì)于MBR(關(guān)于MBR的介紹請(qǐng)讀者參看8.4小節(jié)的DOC 分區(qū))的地址偏移量,MBR的扇區(qū)地址才是整個(gè)SD卡的物理扇區(qū)號(hào)為0的那個(gè)地址,也就是說文件系統(tǒng)并不是處在整個(gè)SD卡最開始的地方,它處在MBR所處的保留區(qū)之后,于是我們可以對(duì)使用FAT32文件系統(tǒng)的SD卡整體布局給出如下圖示) 但是我0x1C到0x1F的4個(gè)字節(jié)為0.不知道是不是問題。 2,引導(dǎo)代碼 FAT32文件系統(tǒng)引導(dǎo)扇區(qū)的512字節(jié)中,90~509字節(jié)為引導(dǎo)代碼,而FAT12/16則是62~509字節(jié)為引導(dǎo)代碼。同時(shí),F(xiàn)AT32還可以利用引導(dǎo)扇區(qū)后的山區(qū)空間存放附加的引導(dǎo)代碼。 一個(gè)FAT卷即使不是可引導(dǎo)文件文件系統(tǒng),也會(huì)存在引導(dǎo)代碼。 3,F(xiàn)SINFO信息扇區(qū) FAT32在保留區(qū)中增加了一個(gè)FSINFO扇區(qū),用以記錄文件系統(tǒng)中空閑簇的數(shù)量以及下一可用簇的簇號(hào)等信息,以供操作系統(tǒng)作為參考。 FSINFO信息扇區(qū)結(jié)構(gòu) 省略 溫馨提示:通常情況下,文件系統(tǒng)的2號(hào)扇區(qū)結(jié)尾也會(huì)被設(shè)置“55 AA”標(biāo)志。6號(hào)扇區(qū)也會(huì)有一個(gè)引導(dǎo)扇區(qū)的備份,相應(yīng)的,7號(hào)扇區(qū)應(yīng)該是一個(gè)備份FSINFO信息扇區(qū)。8號(hào)扇區(qū)可以看做是2號(hào)扇區(qū)的備份,它的結(jié)尾也會(huì)有一個(gè)“55 AA”標(biāo)志。 二,F(xiàn)AT32的FAT表 1 FAT表概述 位于保留區(qū)后的是FAT區(qū),有兩個(gè)完全相同的FAT(File Allocation Table, 文件分配表)表組成,F(xiàn)AT文件系統(tǒng)的名字也是因此而來。 重要說明: 1. 對(duì)于文件系統(tǒng)來說,F(xiàn)AT表有兩個(gè)重要作用:描述簇的分配狀態(tài)以及標(biāo)明文件或目錄的下一簇的簇號(hào)。 2. 通常情況下,一個(gè)FAT把文件系統(tǒng)會(huì)有兩個(gè)FAT表,但有時(shí)也允許只有一個(gè)FAT表,F(xiàn)AT表的具體個(gè)數(shù)記錄在引導(dǎo)扇區(qū)的偏移0x10字節(jié)處。 3. 由于FAT區(qū)緊跟在文件系統(tǒng)保留區(qū)后,所以FAT1在文件系統(tǒng)中的位置可以通過引導(dǎo)記錄中偏移0x0E~0x0F字節(jié)處的“保留扇區(qū)數(shù)”得到。 4. FAT2緊跟在FAT1之后,它的位置可以通過FAT1的位置加上FAT表的大小扇區(qū)數(shù)計(jì)算出來。 2 FAT表的特性 FAT表由一系列大小相等的FAT表項(xiàng)組成,總的說來FAT表有如下特性: 1. FAT32中每個(gè)簇的簇地址,是有32bit(4個(gè)字節(jié))記錄在FAT表中。FAT表中的所有字節(jié)位置以4字節(jié)為單位進(jìn)行劃分,并對(duì)所有劃分后的位置由0進(jìn)行地址編號(hào)。0號(hào)地址與1號(hào)地址被系統(tǒng)保留并存儲(chǔ)特殊標(biāo)志內(nèi)容。從2號(hào)地址開始,每個(gè)地址對(duì)應(yīng)于數(shù)據(jù)區(qū)的簇號(hào),F(xiàn)AT表中的地址編號(hào)與數(shù)據(jù)區(qū)中的簇號(hào)相同。我們稱FAT表中的這些地址為FAT表項(xiàng),F(xiàn)AT表項(xiàng)中記錄的值稱為FAT表項(xiàng)值。 2. 當(dāng)文件系統(tǒng)被創(chuàng)建,也就是進(jìn)行格式化操作時(shí),分配給FAT區(qū)域的空間將會(huì)被清空,在FAT1與FAT2的0號(hào)表項(xiàng)與1號(hào)表項(xiàng)寫入特定值。由于創(chuàng)建文件系統(tǒng)的同時(shí)也會(huì)創(chuàng)建根目錄,也就是為根目錄分配了一個(gè)簇空間,通常為2號(hào)簇,所以2號(hào)簇所對(duì)應(yīng)的2號(hào)FAT表項(xiàng)也會(huì)被寫入一個(gè)結(jié)束標(biāo)記。如下圖所示: 3. 如果某個(gè)簇未被分配使用,它所對(duì)應(yīng)的FAT表項(xiàng)內(nèi)的FAT表項(xiàng)值即用0進(jìn)行填充,表示該FAT表項(xiàng)所對(duì)應(yīng)的簇未被分配。 4. 當(dāng)某個(gè)簇已被分配使用時(shí),則它對(duì)應(yīng)的FAT表項(xiàng)內(nèi)的FAT表項(xiàng)值也就是該文件的下一個(gè)存儲(chǔ)位置的簇號(hào)。如果該文件結(jié)束于該簇,則在它的FAT表項(xiàng)中記錄的是一個(gè)文件結(jié)束標(biāo)記,對(duì)于FAT32而言,代表文件結(jié)束的FAT表項(xiàng)值為0x0FFFFFFF。 5. 如果某個(gè)簇存在壞扇區(qū),則整個(gè)簇會(huì)用FAT表項(xiàng)值0xFFFFFF7標(biāo)記為壞簇,不再使用,這個(gè)壞簇標(biāo)記就記錄在它所對(duì)應(yīng)的FAT表項(xiàng)中。 6. 由于簇號(hào)起始于2號(hào),所以FAT表項(xiàng)的0號(hào)表項(xiàng)與1號(hào)表項(xiàng)不與任何簇對(duì)應(yīng)。FAT32的0號(hào)表項(xiàng)值總是“F8FFFF0F”。如上圖所示。 7. 1號(hào)表項(xiàng)可能被用于記錄臟標(biāo)志,以說明文件系統(tǒng)沒有被正常卸載或者磁盤表面存在錯(cuò)誤。不過這個(gè)值并不重要。正常情況下1號(hào)表項(xiàng)的值為“FFFFFFFF”或“FFFFFF0F”。 8. 在文件系統(tǒng)中新建文件時(shí),如果新建的文件只占用一個(gè)簇,為其分配的簇對(duì)應(yīng)的FAT表項(xiàng)將會(huì)寫入結(jié)束標(biāo)記。如果新建的文件不只占用一個(gè)簇,則在其所占用的每個(gè)簇對(duì)應(yīng)的FAT表項(xiàng)中寫入為其分配的下一簇的簇號(hào),在最后一個(gè)簇對(duì)應(yīng)的FAT表象中寫入結(jié)束標(biāo)記。 9. 新建目錄時(shí),只為其分配一個(gè)簇的空間,對(duì)應(yīng)的FAT表項(xiàng)中寫入結(jié)束標(biāo)記。當(dāng)目錄增大超出一個(gè)簇的大小時(shí),將會(huì)在空閑空間中繼續(xù)為其分配一個(gè)簇,并在FAT表中為其建立FAT表鏈以描述它所占用的簇情況。 10. 對(duì)文件或目錄進(jìn)行操作時(shí),他們所對(duì)應(yīng)的FAT表項(xiàng)將會(huì)被清空,設(shè)置為0以表示其所對(duì)應(yīng)的簇處于未分配狀態(tài)。 要找一個(gè)簇的FAT表項(xiàng),只要用它的簇號(hào)乘以每個(gè)FAT表項(xiàng)的字節(jié)數(shù)即可。Winhex提供了直接跳轉(zhuǎn)到某個(gè)指定FAT表項(xiàng)的功能,單擊position|go to FAT Entry,即可彈出轉(zhuǎn)到FAT項(xiàng)對(duì)話框,在對(duì)話框輸入目標(biāo)FAT項(xiàng)號(hào)碼后單擊OK,光標(biāo)即會(huì)在該FAT項(xiàng)的第一個(gè)字節(jié)上閃爍。 看到這里,我明白了簇地址就是一個(gè)大文件,被拆分成小塊后的一個(gè)個(gè)個(gè)像鏈表一樣的地址。保存在FAT表中。 今天主要看了保留區(qū)和FAT表區(qū)。明天繼續(xù)看數(shù)據(jù)區(qū)。 FAT32文件系統(tǒng)學(xué)習(xí)(2) —— FAT表1、題外話在繼續(xù)本文學(xué)習(xí)FAT32文件系統(tǒng)之前,先來插入一點(diǎn)別的話題。我們都知道U盤有一個(gè)屬性是容量,就拿筆者的U盤為例,筆者手上的U盤是金士頓的DataTraveler G3 4GB的一個(gè)U盤。電腦上顯示的容量如圖1所示為3.75GB。那么這個(gè)3.75GB是怎么計(jì)算出來的呢? 圖 1 系統(tǒng)顯示U盤屬性 我們先來回顧一下上一篇BPB參數(shù)當(dāng)中的Sectors(扇區(qū)總數(shù))這個(gè)參數(shù),這一參數(shù)代表了這個(gè)U盤在出廠時(shí)的總扇區(qū)數(shù),筆者手上這個(gè)是7884672個(gè),可以從圖2中看到。其中每個(gè)扇區(qū)為512 B,也就是說總共可以容納4036952064 B約為3.76GB的數(shù)據(jù)。但是這其中一部分是要用來存放FAT32文件系統(tǒng)的相關(guān)信息參數(shù)的,比如FAT表,BPB等。我們這邊來算一下,首先需要減去1016個(gè)保留扇區(qū),還有兩個(gè)FAT表總共是7684 * 2 = 15368個(gè)扇區(qū),所示還剩下的字節(jié)數(shù)為4036952064 B - ( 1016 + 15368 ) * 512 B = 4028563456 B 正好是圖中顯示的容量。所以可以得出結(jié)論,系統(tǒng)顯示的U盤容量 = ( 總扇區(qū)數(shù) - 保留扇區(qū)數(shù) - FAT表扇區(qū)數(shù) * FAT表個(gè)數(shù) ) * 512 B。經(jīng)計(jì)算可得實(shí)際的使用率是99.79%。所以相對(duì)與整個(gè)U盤來說,F(xiàn)AT32文件系統(tǒng)用于存儲(chǔ)相關(guān)信息部分的損耗是很小的。 圖 2 筆者用上一篇中寫的工具查看了U盤的各項(xiàng)參數(shù) 好了,接下來進(jìn)入正題,繼續(xù)學(xué)習(xí)FAT32文件系統(tǒng)的FAT表部分。 2、本文目錄1、題外話 2、FAT表的讀取 3、FAT表項(xiàng) 4、參考文獻(xiàn) 3、FAT表的讀取首先FAT表一般來說有兩張,另一張用于備份。兩張表是前后緊挨在一起的,只要計(jì)算出了FAT1表的偏移之后加上FAT表的大小就可以得到FAT2表的偏移。FAT1表的偏移地址計(jì)算公式如下[4] FAT1表偏移 = 保留扇區(qū)數(shù) * 每扇區(qū)字節(jié)數(shù) 由圖2可知,在本例中,F(xiàn)AT1表的偏移 = 1016 * 512 B = 520192 = 0x7F000。同理: FAT2表的偏移 = FAT1+FAT表的大小 = (保留扇區(qū)數(shù) + FAT表扇區(qū)數(shù)) * 每扇區(qū)字節(jié)數(shù) 在本例中,F(xiàn)AT2表的偏移 = (1016 + 7684) * 512 B = 4454400 = 0x43F800。用上一篇中講到的程序可以讀取出兩張F(tuán)AT表的內(nèi)容,一般情況下兩張表的內(nèi)容應(yīng)該是完全一樣的。筆者讀取了第一張F(tuán)AT表起始部分的內(nèi)容,如圖3所示: 圖 3 FAT表起始部分內(nèi)容 4、FAT表項(xiàng)在分析FAT表之前先來說明一下FAT的構(gòu)成。FAT表即文件分配表(File Allocation Table)。FAT32文件表是由一個(gè)個(gè)表項(xiàng)組成的一張表,其中每一個(gè)表項(xiàng)由一個(gè)32位的二進(jìn)制組成,其值對(duì)應(yīng)了相應(yīng)簇的使用情況,如2號(hào)表項(xiàng)對(duì)應(yīng)了2號(hào)簇的使用情況,3號(hào)表項(xiàng)對(duì)應(yīng)了3號(hào)簇的使用情況,依此類推。(但是第0和第1項(xiàng)例外,下面會(huì)有說明)。每個(gè)表項(xiàng)對(duì)應(yīng)數(shù)值的含義如表1所示[2]:
表 1 表項(xiàng)數(shù)值含義 具體每一項(xiàng)填寫的內(nèi)容規(guī)則如下表所示:如果該簇是文件的最后一簇,填入的值為0x0FFFFFFF;如果該簇不是文件的最后一簇,則填入的值為該文件占用的下一簇號(hào)(所以我們可以看到在FAT32中文件是以簇鏈的形式保存起來的)。下面我們根據(jù)實(shí)際情況,圖3來分析一下FAT表的含義。 FAT表第0項(xiàng)(0x00000000~0x00000003): 0x0FFFFF8 FAT表第1項(xiàng)(0x00000004~0x00000007): 0xFFFFFFFF 這兩項(xiàng)不代表任何簇的使用情況,而是FAT表的表頭,表征了介質(zhì)描述,是固定值,所以0x00和0x01這兩個(gè)簇號(hào)是不用的,簇號(hào)的下標(biāo)從2開始。其中1號(hào)表項(xiàng)可能被用于記錄臟標(biāo)志,以說明文件系統(tǒng)沒有被正常卸載或者磁盤表面存在錯(cuò)誤。接下來 FAT表第2項(xiàng)(0x00000008~0x0000000B): 0x0FFFFFFF 第2項(xiàng)存儲(chǔ)的是第2簇的使用情況,通常第2簇存儲(chǔ)的是文件系統(tǒng)的根目錄。雖然在FAT32文件系統(tǒng)中,根目錄的位置不再硬性地固定,可以存儲(chǔ)在分區(qū)內(nèi)可尋址的任意簇內(nèi),不過通常根目錄是最早建立的(格式化就生成了)目錄表。所以,我們看到的情況基本上都是根目錄首簇緊鄰FAT2,占簇區(qū)順序上的第1個(gè)簇(即2號(hào)簇)。同時(shí),F(xiàn)AT32文件系統(tǒng)將根目錄當(dāng)做普通的數(shù)據(jù)文件來看,所有沒有了目錄項(xiàng)數(shù)的限制,在需要的時(shí)候可以分配空簇,存儲(chǔ)更多的目錄項(xiàng)[1]。 這一項(xiàng)的值為0x0FFFFFFF ,說明根目錄占用且只占用了1個(gè)簇。 FAT表第3 …… 這里再穿插一點(diǎn)題外話,F(xiàn)AT32格式文件分配的最小單位是簇。也就是說你存儲(chǔ)了一個(gè)實(shí)際大小1kB的文件,那么它占用的存儲(chǔ)空間還是1簇(在這里換算成大小即為8*512B = 4KB)。筆者以一個(gè)實(shí)際的例子來說明一下:在U盤中放入一個(gè)8B大小的temp.txt文件,然后查看文件屬性的時(shí)候發(fā)現(xiàn)其占用空間是4KB,和我們上面講的理論符合。 圖 4 temp.txt的大小和占用空間 看了下篇幅也差不多了,那么本文關(guān)于FAT表的部分到此結(jié)束。其實(shí)本來也沒多少內(nèi)容,筆者想到哪就扯到哪,胡扯了些其他的東西。剩下的數(shù)據(jù)區(qū)部分就留到下一篇當(dāng)中再講好了。同樣的,本文當(dāng)中有一些內(nèi)容是筆者自己思考理解甚至推測(cè)出來的,如果有錯(cuò)誤的地方歡迎指正,以免誤人子弟了(笑)。 FAT32文件系統(tǒng)學(xué)習(xí)(3) —— 數(shù)據(jù)區(qū)(DATA區(qū))今天繼續(xù)學(xué)習(xí)FAT32文件系統(tǒng)的數(shù)據(jù)區(qū)部分(Data區(qū))。其實(shí)這一篇應(yīng)該是最有意思的,我們可以通過在U盤內(nèi)放入一些文件,然后在程序中讀取出來;反過來也可以用程序在U盤內(nèi)寫入一下數(shù)據(jù),然后在windows下可以看到寫入的文件。這些筆者都會(huì)在這篇文章中演示(后來發(fā)現(xiàn)并沒有成功,不過筆者也找到相關(guān)的原因,詳見后來的更新部分吧:) )。同時(shí),在寫這篇文章的時(shí)候筆者也發(fā)現(xiàn)了許多意想不到的規(guī)律。 1、本文目錄1、讀取根目錄 2、短文件名目錄項(xiàng) 3、長(zhǎng)文件名目錄項(xiàng) 4、U盤寫入文件夾 5、參考文獻(xiàn) 2、讀取根目錄兩張F(tuán)AT之后的所有扇區(qū)都是數(shù)據(jù)區(qū)部分。我們?cè)偻ㄟ^圖1來回顧一下整個(gè)FAT32文件系統(tǒng)的分布規(guī)則。 圖 1 FAT32文件系統(tǒng)分布圖 通常情況下根目錄都是位于數(shù)據(jù)區(qū)頭部的,前面也提到過,有文獻(xiàn)上說是因?yàn)橐坏︰盤格式化完畢之后,根目錄就創(chuàng)建好了。本著探究的精神,筆者嘗試格式化了一下U盤,發(fā)現(xiàn)其實(shí)并沒有創(chuàng)建根目錄。不過一旦有文件操作,馬上就會(huì)創(chuàng)建根目錄,因?yàn)檫@時(shí)整個(gè)數(shù)據(jù)區(qū)都是空的,所以自然是寫入數(shù)據(jù)區(qū)的頭部。到頭來其實(shí)道理是一樣的,也就是說根目錄一般情況下都是在數(shù)據(jù)區(qū)的頭部(第2簇)。 數(shù)據(jù)區(qū)偏移計(jì)算 經(jīng)過前兩篇關(guān)于BPB和FAT部分學(xué)習(xí)之后,我們就可以計(jì)算出數(shù)據(jù)區(qū)頭部的偏移: 數(shù)據(jù)區(qū)偏移 = (保留扇區(qū)數(shù) + FAT表扇區(qū)數(shù) * FAT表個(gè)數(shù)(通常為2) + (起始簇號(hào)-2) * 每簇扇區(qū)數(shù)) * 每扇區(qū)字節(jié)數(shù) 筆者首先格式化了U盤,通過偏移讀取出了數(shù)據(jù)區(qū)的頭部,發(fā)現(xiàn)都是0x00。 題外話 這里又要插一些題外話了,筆者試著改了一下U盤的卷標(biāo),把它改名為“FAT”。然后還記得BPB當(dāng)中有一個(gè)參數(shù)叫做卷標(biāo)嗎?筆者看了下發(fā)現(xiàn)卷標(biāo)這個(gè)參數(shù)還是“NO NAME”并沒有改變。這時(shí)筆者把數(shù)據(jù)區(qū)的頭部讀取了出來,如圖2所示: 圖2 卷標(biāo) 原來被寫在了這里。最后經(jīng)筆者的測(cè)試,卷標(biāo)最長(zhǎng)長(zhǎng)度是11個(gè)字節(jié),偏移從0x00~0x0A,而偏移0x0B處的值0x08值的意思就是卷標(biāo)(關(guān)于此處值的意思相面還會(huì)詳細(xì)描述)。因?yàn)檫@個(gè)U盤其實(shí)還沒有寫入過任何數(shù)據(jù),所以卷標(biāo)才會(huì)顯示在數(shù)據(jù)區(qū)的開頭,但是如果換種情況呢,文件系統(tǒng)又是如何找到卷標(biāo)的呢?筆者查閱了相關(guān)資料后發(fā)現(xiàn),卷標(biāo)一般都是寫在根目錄的下的,如果發(fā)現(xiàn)根目錄項(xiàng)的其中一項(xiàng)其0x0B偏移處的值為0x08那么讀取該項(xiàng)的前11個(gè)字節(jié)即為卷標(biāo)。 3、短文件名目錄項(xiàng)短文件名目錄項(xiàng)參數(shù) 好,回到正題。先來講一下理論的東西:目錄區(qū)是由一個(gè)個(gè)目錄項(xiàng)構(gòu)成,類似于FAT表。其中每一個(gè)目錄項(xiàng)占用32個(gè)字節(jié),可以是代表長(zhǎng)文件名目錄項(xiàng)、文件目錄項(xiàng)、子目錄項(xiàng)等。對(duì)于短文件名格式的目錄項(xiàng),其參數(shù)的含義如表1所示(不會(huì)畫這種表,從別處引用了一個(gè))[1]: 表1 FAT32短文件名目錄項(xiàng)參數(shù)表 參數(shù)解釋 用一個(gè)實(shí)際的例子來解釋一下這些參數(shù)的意思,首先創(chuàng)建一個(gè)短文件名文件,如“file1.txt”,讀取根目錄,如圖3所示: 圖3 file1.txt 短文件名目錄項(xiàng) 先不管其他數(shù)據(jù),我們來看一下紅色矩形框部分的數(shù)據(jù),它就是一個(gè)短目錄項(xiàng)。我們來一個(gè)個(gè)對(duì)比表1的參數(shù)進(jìn)行說明:
表2 file1.txt 參數(shù)解釋 注釋1:01111 000010 11100 1)這里高5位代表小時(shí),由于2^5 = 32,足夠表示24小時(shí),這邊01111(2進(jìn)制) = 15(10進(jìn)制); 2)次6位代表分鐘,同理2^6 = 64,足夠表示60分鐘,這邊000010(2進(jìn)制) = 2; 3)低5位表示秒的1/2, 計(jì)算結(jié)果需要加上毫秒位上的進(jìn)位,這邊11100(2進(jìn)制) = 28(10進(jìn)制),所以秒數(shù) = 28*2 = 56,再加上毫秒上的進(jìn)位1所以結(jié)果為57。 注釋2:0100010 1000 01000 1)這里高7位代表從1980年開始的年數(shù),筆者計(jì)算了下可以到2108年,總之還有90多年可以使用,這邊0100010(2進(jìn)制) = 34,所以年份 = 1980+34 = 2014; 2)次4位代表月份,2^4=16,可以表示12個(gè)月份,這邊 1000(2進(jìn)制) = 8(10進(jìn)制); 3)低5位代表日期,2^5 = 32,可以表示28~31天,這邊 01000(2進(jìn)制) = 8(10進(jìn)制)。 這樣除了文件起始簇號(hào)字段,其他字段的意思和計(jì)算方法都弄清楚了。下面來看一下文件起始簇號(hào),首先根據(jù)高低各16位,計(jì)算出完整的文件起始簇號(hào) = 0x00000005 ,文件起始地址偏移的計(jì)算: 文件起始地址 = (保留扇區(qū)數(shù) + FAT表扇區(qū)數(shù) * FAT表個(gè)數(shù)(2) + (文件起始簇號(hào)-2)*每簇扇區(qū)數(shù))*每扇區(qū)字節(jié)數(shù) 本例中計(jì)算結(jié)果為0x4010,然后到這個(gè)地址讀取內(nèi)容并切入到磁盤文件中(詳細(xì)操作參考第一篇文章),如圖4所示,windows下打開內(nèi)容如圖5所示: 圖4 圖5 文件內(nèi)容 這個(gè)時(shí)候再去看一下FAT表的5號(hào)簇,計(jì)算方式在上一篇當(dāng)中,結(jié)果如圖6所示: 圖 6 FAT表5號(hào)表項(xiàng) 紅色矩形框的位置就是5號(hào)簇的位置,可以看到值0x0FFFFFFF,意思就是文件在這一簇結(jié)束了。 (具體不同數(shù)值的含義詳見上一篇)。如果這里文件大小超過1簇,那么這個(gè)值應(yīng)該是下一簇的簇號(hào),繼續(xù)讀取下一簇的內(nèi)容即可。雖然我們知道了文件占用的空間是1簇,但是怎么知道文件具體的大小呢?再回過頭來看上面的短文件目錄項(xiàng),最后一個(gè)屬性是文件長(zhǎng)度,上面已經(jīng)計(jì)算得到為12,“Hello World!”的長(zhǎng)度正好是12:)。 至此短文件目錄項(xiàng)應(yīng)該已經(jīng)分析的差不多了。 4、長(zhǎng)文件名目錄項(xiàng)長(zhǎng)文件名目錄項(xiàng)參數(shù) 下面是長(zhǎng)文件名目錄項(xiàng),筆者思考了好久該怎么把它講清楚,畢竟理解是一回事,講清楚就是另一回事了。 在講長(zhǎng)文件目錄項(xiàng)之前先來說一下FAT32的一個(gè)很重要的特性,支持長(zhǎng)文件名。長(zhǎng)文件名也是記錄在目錄項(xiàng)當(dāng)中的,區(qū)別與短目錄項(xiàng)的是,前者可能會(huì)占據(jù)好幾個(gè)目錄項(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)來記錄和編輯,并隱藏起短文件名[2]。 當(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。 那么系統(tǒng)是如何判斷當(dāng)前目錄項(xiàng)是短文件名目錄項(xiàng)呢還是長(zhǎng)文件名目錄項(xiàng),這里關(guān)鍵是看目錄項(xiàng)的第12個(gè)字節(jié)的值,如果為0x0F時(shí)則系統(tǒng)認(rèn)為是長(zhǎng)目錄項(xiàng)。而如果是舊版本的系統(tǒng)看到第12個(gè)字節(jié)是0x0F則認(rèn)為是異常而忽略掉。這里可以回過頭去看一下短文件名目錄項(xiàng),第12個(gè)字節(jié)是文件屬性字節(jié),0x0F即為全1是無(wú)效的,所以系統(tǒng)認(rèn)為是異常。系統(tǒng)將長(zhǎng)文件名以13個(gè)字符為單位進(jìn)行切割,每一組占據(jù)一個(gè)目錄項(xiàng)。所以可能一個(gè)文件需要多個(gè)目錄項(xiàng),這時(shí)長(zhǎng)文件名的各個(gè)目錄項(xiàng)按倒序排列在目錄表中,以防與其他文件名混淆。 這樣講可能還是很抽象,先來看一下長(zhǎng)文件名目錄項(xiàng)的參數(shù),如表3所示[1]: 表3 長(zhǎng)文件名目錄項(xiàng)參數(shù)表 參數(shù)解釋 然后還是以一個(gè)實(shí)際的例子來說明,在根目錄區(qū)讀入一個(gè)長(zhǎng)文件名目錄項(xiàng),如圖7所示: 圖7 長(zhǎng)文件名目錄項(xiàng) 圖中選定部分即為多個(gè)長(zhǎng)文件名目錄項(xiàng)。我們來慢慢分析。系統(tǒng)在讀入一個(gè)目錄項(xiàng)的時(shí)候首先查看它的第12個(gè)字節(jié),發(fā)現(xiàn)是0x0F,所以認(rèn)為這是一個(gè)長(zhǎng)文件名目錄項(xiàng)。我們來看長(zhǎng)文件名目錄項(xiàng)的參數(shù),如表4所示:
表4 長(zhǎng)文件名目錄項(xiàng)參數(shù)解釋 注釋1:01000010 第7位為1,說明是文件最后一個(gè)目錄項(xiàng)目,低5位為順序 0010(2進(jìn)制) = 2(10進(jìn)制),說明這是第2個(gè)長(zhǎng)目錄項(xiàng),且是最后一個(gè)目錄項(xiàng)。即為這個(gè)長(zhǎng)文件名占用了兩個(gè)目錄項(xiàng)。 注釋2:Unicode 百度百科Unicode 點(diǎn)我詳細(xì)解釋 這邊有3個(gè)Unicode區(qū),加起來正好是26個(gè)字節(jié)即13個(gè)Unicode碼,所以這就是為什么上面講的以13個(gè)字符為單位切割。因?yàn)檫@是第2個(gè)目錄項(xiàng),所以后面應(yīng)該還有第1個(gè)目錄項(xiàng),繼續(xù)分析下一個(gè)目錄項(xiàng)其余參數(shù)同上,看一下3個(gè)Unicode分別是“LongL” “engthF” “il”而0x00的屬性字節(jié)是01,說明這是第一個(gè)。至此這個(gè)長(zhǎng)文件名讀取完畢了。按照倒序(這里也解釋了前面說的倒序的意思)的順序拼接起來的話就是“LongLengthFilename”——這就是這個(gè)文件的文件名。 下面再來看一下下一個(gè)目錄項(xiàng),長(zhǎng)文件名目錄項(xiàng)后面還會(huì)跟一個(gè)短文件名目錄項(xiàng),這個(gè)目錄項(xiàng)記錄了除文件名以外的這個(gè)文件的信息,而文件名部分則用上面提到的短文件名目錄項(xiàng)替換。所以讀取方法和短文件名目錄項(xiàng)是一樣的,這里只看一下文件屬性字節(jié),偏移為0x0B,值為0x10=(00010000) 根據(jù)短文件名目錄項(xiàng)參數(shù)的意思,這個(gè)文件是一個(gè)子目錄。其余參數(shù)讀者可以根據(jù)上面提到的計(jì)算方法得出。 最后再來補(bǔ)上剛才的校驗(yàn)碼計(jì)算方法: int i, j = 0, chksum=0; for (i = 11; i > 0; i--) chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; 其中shortname即長(zhǎng)文件名目錄項(xiàng)對(duì)應(yīng)的短文件名,所以這個(gè)校驗(yàn)碼需要等到讀完短文件名目錄項(xiàng)之后才可以計(jì)算。這一段程序是筆者從網(wǎng)上摘來的,還沒有時(shí)間驗(yàn)證一下。 5、U盤寫入文件夾這樣關(guān)于數(shù)據(jù)區(qū)的部分差不多就講完了。 最后在做一點(diǎn)有趣的事情,嘗試向磁盤的扇區(qū)中寫入一些數(shù)據(jù),然后看是否會(huì)生成這個(gè)文件。為了方便起見,這里直接在根目錄創(chuàng)建一個(gè)文件夾好了, 文件夾的名字叫做root, 創(chuàng)建時(shí)間日期2014/8/8 18:18:18 訪問日期 2014/8/8 最近修改時(shí)間日期 2014/8/8 18:18:18 起始簇低16位 04 00 起始簇高16位 00 00 文件長(zhǎng)度 0 同時(shí)修改2個(gè)FAT表第4項(xiàng)為0x0FFFFFFF 這樣應(yīng)該就可以了,好了,開始編碼: // 短文件名目錄項(xiàng)數(shù)據(jù)結(jié)構(gòu) typedef struct ShortDirItem { char strFilename[8]; char strExtension[3]; char attribute; char reserved; char millisecond; unsigned short createTime; unsigned short createDate; unsigned short accessDate; unsigned short highWordCluster; unsigned short updateTime; unsigned short updateDate; unsigned short lowWordCluster; unsigned int filesize;17 }ShortDirItem; // 定位到FAT1表 SetFilePointer(hDisc, 1016*512, 0, FILE_BEGIN); DWORD dwNumber2Read = 512; // 實(shí)際讀取的字節(jié)數(shù) DWORD dwRealNumber; // 分配緩沖區(qū) char* buffer = new char[512]; // 讀取一個(gè)扇區(qū)的數(shù)據(jù) BOOL bRet = ReadFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL); // 把4第項(xiàng)改為 0x0FFFFFFF buffer[12] = buffer[13] = buffer[14] = 0xFF; buffer[15] = 0x0F; // 寫回FAT1 bRet = WriteFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL); // 定位到FAT2表 SetFilePointer(hDisc, (1016+7684)*512, 0, FILE_BEGIN); // 把4第項(xiàng)改為 0x0FFFFFFF bRet = WriteFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL); // 定位到根目錄 SetFilePointer(hDisc, (1016+7684*2)*512, 0, FILE_BEGIN); // 讀取根目錄扇區(qū) bRet = ReadFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL); // 準(zhǔn)備數(shù)據(jù) ShortDirItem* item = new ShortDirItem(); strcpy(item->strFilename, "root"); strcpy(item->strExtension, " "); item->attribute = 0x10; item->millisecond = 0x00; item->createTime = 0x9249; item->createDate = 0x4508; item->accessDate = 0x4508; item->highWordCluster = 0x0000; item->updateTime = 0x9249; item->updateDate = 0x4508; item->lowWordCluster = 0x0004; item->filesize = 0x00; // 修改根目錄數(shù)據(jù) char* pData = (char*)item; for (int i = 32; i < 64; ++i) { buffer[i] = *(pData++); } // 寫回根目錄 bRet = WriteFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL); // 掃尾工作,釋放緩沖區(qū),關(guān)閉句柄 delete[] buffer;48 delete item;49 CloseHandle(hDisc); 但是筆者發(fā)現(xiàn)在win7(準(zhǔn)確的說是win7、vista、win8,XP下獲取管理員權(quán)限即可執(zhí)行)下調(diào)用WriteFile函數(shù)無(wú)法將數(shù)據(jù)寫入U(xiǎn)盤,可能是由于系統(tǒng)保護(hù)措施的關(guān)系,由于時(shí)間關(guān)系,筆者也沒去深究。 后來筆者專門去查找了相關(guān)資料,總的來說原因確實(shí)是因?yàn)橄到y(tǒng)保護(hù)措施的關(guān)系導(dǎo)致WriteFile函數(shù)操作的失敗,具體的解釋如下: 首先是msdn上的解釋 http://msdn.microsoft.com/en-us/library/windows/hardware/ff551353(v=vs.85).aspx。大概意思是說在win7和vista上加入了一些新的特性,為了能夠更好得保護(hù)系統(tǒng),如果應(yīng)用程序沒有獨(dú)占的權(quán)限就直接對(duì)裝有文件系統(tǒng)的存儲(chǔ)設(shè)備進(jìn)行寫入操作的話,這個(gè)操作是會(huì)被拒絕的。筆者上面的程序通過GetLastError()函數(shù)得到的ErroeCode=5,意思也確實(shí)是拒絕訪問。那么到底要如何寫入呢,msdn上給出了以下幾種情況: Write operations on a DASD volume handle will succeed if the file system is not mounted, or if: The sectors being written to are the boot sectors. The sectors being written to reside outside file system space. The file system has been locked implicitly by requesting exclusive write access. The file system has been locked explicitly by sending down a lock/dismount request. The write request has been flagged by a kernel-mode driver that indicates that this check should be bypassed. The flag is called SL_FORCE_DIRECT_WRITE and it is in the IrpSp->flags field. This flag is checked by both the file system and storage drivers. 這里比較方便的做法可以采用第4種,即顯示地發(fā)送一個(gè)鎖定驅(qū)動(dòng)的請(qǐng)求,然后再嘗試寫入。具體做法參考這個(gè)帖子22L吧,筆者打算去嘗試一下,成功的話再來更新結(jié)果。 好了,看了下篇幅這篇文章也差不多可以結(jié)束了。FAT32文件系統(tǒng)其實(shí)差不多也都學(xué)習(xí)完了,為了鞏固學(xué)習(xí)內(nèi)容,筆者打算接下去根據(jù)前面所學(xué)的知識(shí),并去了解一下windows快速格式化FAT32的機(jī)制,嘗試自己格式化U盤,還可以根據(jù)FAT32的原理嘗試刪除數(shù)據(jù)的恢復(fù)等,總之還是有很多事情可以做的。 最后的最后,如果文章當(dāng)中有任何錯(cuò)誤或者遺漏指出,歡迎指出,謝謝。 FAT32 FAT區(qū)__FAT表解析一、 FAT 表概述 位置:緊跟在文件系統(tǒng)的“保留區(qū)”之后 ; 有兩個(gè)數(shù)據(jù)結(jié)構(gòu)完全相同的FAT(FAT,File Allocation Tbale 文件分配表)組成。 作用:FAT表項(xiàng),描述文件系統(tǒng)內(nèi)的簇分配狀態(tài),說明文件系統(tǒng)內(nèi)數(shù)據(jù)所分配的連續(xù)簇的順序關(guān)系(即表明文件或目錄的下一簇的序號(hào))。 常規(guī)規(guī)則: · 數(shù)量:通常情況下一個(gè)FAT 文件系統(tǒng)會(huì)有兩個(gè)FAT 表, 但有時(shí)候也會(huì)允許只有一個(gè)FAT 表, FAT 表的具體個(gè)數(shù)記錄在引導(dǎo)扇區(qū)的 偏移 0x10 字節(jié)處。 · 位置:因?yàn)镕AT區(qū)位于文件系統(tǒng)的保留區(qū)之后,所以FAT1在文件系統(tǒng)中的位置可以通過引導(dǎo)記錄中偏移0x0E~0x0F 字節(jié)處的“保留扇區(qū)”數(shù)得到。 · FAT2 緊跟在FAT1之后, 它的位置可以通過FAT1的位置加上每個(gè)FAT 表的大小扇區(qū)數(shù)獲得。 FAT 表中記錄了每個(gè)文件的簇鏈結(jié)構(gòu); FAT 表中記錄的與數(shù)據(jù)區(qū)簇對(duì)應(yīng)的表項(xiàng),從0號(hào)標(biāo)記開始至當(dāng)前數(shù)據(jù)區(qū)所分配的簇的最大數(shù)值,記錄簇信息到FAT 項(xiàng);但是注意:其中 0號(hào)~1號(hào)簇的值都是操作系統(tǒng)預(yù)先不留設(shè)定的特殊標(biāo)記,而數(shù)據(jù)區(qū)的起始簇是2號(hào)簇。 二、、FAT 表的特性 FAT 表由一些列大小相等的表項(xiàng)組成,有如下特性: · FAT32 中每個(gè)簇的狀態(tài),使用32bit(4字節(jié))記錄在FAT表中。 FAT 表中的所有字節(jié)位置以 4個(gè)字節(jié)為單位進(jìn)行劃分;并以所有劃分后的位置由0進(jìn)行地址編號(hào)。“0號(hào) 和 1號(hào)” 地址被系統(tǒng)保留并存儲(chǔ)特殊標(biāo)識(shí)內(nèi)容。從 2號(hào) 地址開始, 每個(gè)地址對(duì)應(yīng)于數(shù)據(jù)區(qū)的簇號(hào),FAT 表中的地址編號(hào)與數(shù)據(jù)區(qū)中的簇號(hào)相同。稱FAT 中的這些四字節(jié)一組劃分的項(xiàng)的地址為 FAT 表項(xiàng),FAT表項(xiàng)中記錄的值為FAT 表項(xiàng)值。(簇編號(hào)與簇內(nèi)內(nèi)容關(guān)系如果 Map中的鍵-值 關(guān)系相同) 當(dāng)文件系統(tǒng)創(chuàng)建時(shí)(就是格式化操作時(shí)), 分配給FAT 區(qū)域的空間將會(huì)被清空, 在FAT1與FAT2 的0號(hào)和1號(hào)表項(xiàng)寫入特定值。由于創(chuàng)建文件系統(tǒng)的同時(shí),也會(huì)創(chuàng)建根目錄, 也就是為根目錄分配了一個(gè)簇空間,通常為2號(hào)簇,所以2號(hào)簇所對(duì)應(yīng)的“2號(hào)FAT表項(xiàng)”也會(huì)被寫入一個(gè)結(jié)束標(biāo)記。 · 如果某個(gè)簇未被使用,他所對(duì)應(yīng)的FAT 表項(xiàng)內(nèi)的FAT 表項(xiàng)值即用0進(jìn)行填充,表示該FAT 表項(xiàng)所對(duì)應(yīng)的簇未被分配使用 · 當(dāng)某個(gè)簇被分配使用時(shí),那么他所對(duì)應(yīng)的FAT表項(xiàng)的值為文件的下一個(gè)存儲(chǔ)文件的簇號(hào)。 如果該文件結(jié)束于該簇,則在它的FAT表項(xiàng)中記錄的是一個(gè)文件結(jié)束標(biāo)記,對(duì)于FAT32 而言,代表文件結(jié)束的FAT表項(xiàng)值為0x0FFFFFFF。 · 如果某個(gè)簇存在壞扇區(qū),則整個(gè)簇會(huì)用FAT 表項(xiàng)值0x0FFFFFF7 標(biāo)記為壞簇, 不再使用,這個(gè)壞簇標(biāo)記就記錄在它所對(duì)應(yīng)的FAT表項(xiàng)中。 · 由于簇號(hào)起始于2, 所以FAT表的0號(hào)表項(xiàng)與1號(hào)表項(xiàng)不予任何簇對(duì)應(yīng)。 FAT32 的0號(hào)表項(xiàng)值總是“F8FFFF0F” 注意:可以搜索扇區(qū)偏移0字節(jié)處的該值(F8FFF0F)以查找FAT表。 · 1號(hào)表項(xiàng)可能被用于記錄“臟標(biāo)志”, 以說明文件系統(tǒng)沒有被正常卸載或者磁盤表面存在錯(cuò)誤。 不過此值似乎不重要,正常情況下,1號(hào)表項(xiàng)值“FFFFFFFF”或“FFFFFF0F” 項(xiàng)內(nèi)容填寫規(guī)則: ·在文件系統(tǒng)中新建文件時(shí),如果新建的文件只有一個(gè)簇,為其分配的簇所對(duì)應(yīng)的FAT表項(xiàng)將會(huì)被寫入結(jié)束標(biāo)記。如果新建的文件不只占用一個(gè)簇,則在其所占用的每個(gè)簇對(duì)應(yīng)的FAT表項(xiàng)中寫入為其分配的下一個(gè)簇的簇號(hào),在最后一個(gè)簇對(duì)應(yīng)的FAT 表項(xiàng)中寫入結(jié)束標(biāo)記。 · 新建目錄時(shí),只為其分配一個(gè)簇的空間,對(duì)應(yīng)的FAT 表項(xiàng)中寫入結(jié)束標(biāo)記。當(dāng)目錄增大超過一個(gè)簇的大小時(shí),將會(huì)在空閑空間中繼續(xù)為其分配一個(gè)簇,并在FAT 表中為其建立FAT 表鏈以描述它所占用的簇的情況。 · 對(duì)文件或目錄進(jìn)行刪除操作時(shí),他們所對(duì)應(yīng)的FAT 表項(xiàng)將會(huì)被清空,設(shè)置為0以表示其所對(duì)應(yīng)的簇處于未分配的狀態(tài)。 三、 FAT表的使用 一個(gè)文件的“起始簇號(hào)”記錄在它的目錄項(xiàng)中, 該文件的 "其他簇" 則用一個(gè)簇連結(jié)構(gòu)記錄在FAT 表中。 如果一個(gè)簇所對(duì)應(yīng)的FAT表項(xiàng)的表項(xiàng)值為非零, 則表明該簇已經(jīng)被分配使用了,但是這時(shí)表項(xiàng)值可能為兩種情況,一個(gè)是一個(gè)文件的下一個(gè)簇號(hào)值,也有可能是一個(gè)文件的結(jié)束標(biāo)記0x0FFFFFFF,或者是一個(gè)壞簇標(biāo)記0x0FFFFFF7 。 如果要尋找一個(gè)文件的下一個(gè)簇,只需要查看該文件的目錄項(xiàng)中描述的起始簇號(hào)所對(duì)應(yīng)的FAT項(xiàng),如果該文件只有一個(gè)簇,則此處的值為一個(gè)結(jié)束標(biāo)記0x0FFFFFFF;如果該文件不只一個(gè)簇,則此處 的值是它的下一個(gè)簇的簇號(hào)。 >> 查詢簇連接結(jié)構(gòu)模擬步驟: 當(dāng)我們要尋找某個(gè)文件時(shí), 首先從該文件的“目錄項(xiàng)”中獲取該文件的第一“簇”的簇號(hào),然后根據(jù)“第一簇”的“簇號(hào) N”,然后根據(jù)N 從FAT區(qū)的FAT表找出N簇號(hào)所對(duì)應(yīng)的FAT 表項(xiàng),查看FAT 表項(xiàng)的內(nèi)容: 若是文件結(jié)束,該表項(xiàng)值為 0x0FFFFFFF; 若是沒有結(jié)束,而該文件的大小超出一個(gè)簇,則N所對(duì)應(yīng)的FAT表項(xiàng)的表項(xiàng)值為該文件下一個(gè)簇的簇號(hào),然后再找到下一個(gè)簇號(hào)N+1 所對(duì)應(yīng)的FAT表項(xiàng),查看其表項(xiàng)值,依次類推,就推出了一個(gè)文件在FAT表中的 簇鏈連接結(jié)構(gòu); 也或者表項(xiàng)值為 0xFFFFFFF7 壞簇標(biāo)識(shí)。 >> 其他 查找FAT 表項(xiàng):要找到一個(gè)簇的FAT 表項(xiàng),只要用他的 簇號(hào)乘以每個(gè)FAT 表項(xiàng)的字節(jié)數(shù)即可 。對(duì)于FAT32而言,每個(gè)FAT 表項(xiàng)占用4個(gè)四字節(jié), 如果我們尋找9號(hào)簇的表項(xiàng)位置,則用 4*9=36,也就是說位于FAT 表內(nèi)偏移36(0x24)字節(jié)處。 注意: WinHex 提供了直接跳轉(zhuǎn)到某個(gè)指定FAT 表項(xiàng)的功能。 文件系統(tǒng)大小的上限值卻絕育FAT 項(xiàng)的大小。 簇鏈中的每個(gè)FAT 項(xiàng)記錄著下一個(gè)簇的簇地址,F(xiàn)AT 項(xiàng)所能表示的數(shù)字有一個(gè)上限,這個(gè)上限也就是文件系統(tǒng)中的最大簇號(hào)。 FAT 32文件系統(tǒng)的FAT 項(xiàng)只使用了32bit 中的28bit ,因此只能描述 268435456個(gè)簇(實(shí)際上還要考略小于這個(gè)值,因?yàn)檫@其中還包含了結(jié)束標(biāo)志及壞簇標(biāo)志的保留值)。 操作系統(tǒng)通過檢測(cè)FAT 表中的表項(xiàng)來確定文件系統(tǒng)中的各個(gè)簇是否被分配使用。當(dāng)我們?cè)赪indows 下右擊某個(gè)FAT 分區(qū)查看其屬性時(shí),顯示的已用空間和未用空間就是根據(jù)FAT 表統(tǒng)計(jì)而來的。 有時(shí)我們會(huì)遇到,查看屬性時(shí)發(fā)現(xiàn)已用空間并沒有減少,但存儲(chǔ)的文件卻不見了。這是因?yàn)槟承┎《驹谀承┪募哪夸涰?xiàng)中寫入了刪除標(biāo)記,但并沒有清楚FAT 表內(nèi)的簇鏈所至。 FAT32文件系統(tǒng)的存儲(chǔ)組織結(jié)構(gòu)對(duì)磁盤的物理結(jié)構(gòu),邏輯結(jié)構(gòu)和存儲(chǔ)結(jié)構(gòu)有了比較深入的了解后,我們來仔細(xì)探討FAT32文件系統(tǒng)的存儲(chǔ)組織結(jié)構(gòu)。說到文件系統(tǒng)的組織結(jié)構(gòu),我們應(yīng)該馬上意識(shí)到,這指的是文件系統(tǒng)在同一個(gè)分區(qū)內(nèi)的組織結(jié)構(gòu),在這個(gè)話題上,我們完全可以不管分區(qū)之外的所有事情。 為了分析FAT32文件系統(tǒng)的存儲(chǔ)組織結(jié)構(gòu),我們來建立一個(gè)實(shí)實(shí)在在的文件系統(tǒng):將U盤插入電腦,將U盤格式化成FAT32分區(qū)格式: 以建好的U盤FAT32文件系統(tǒng)為基礎(chǔ),下面從文件系統(tǒng)的各個(gè)組成來分別加以介紹。 分區(qū)引導(dǎo)扇區(qū)DBR 用winhex打開U盤顯示如下: 這是FAT32分區(qū)引導(dǎo)記錄,定義如下: 偏移00H: 3字節(jié)的 跳轉(zhuǎn)指令 EB 58 90,跳過下面的BPB和擴(kuò)展BPB部分 偏移03H:8字節(jié)的硬盤分區(qū)類型文本字符名:4D 53 44 4F 53 35 2E 30 即:MSDOS5.0 偏移0BH: 25字節(jié)的分區(qū)參數(shù)塊(BPB),細(xì)分如下: 偏移0BH:扇區(qū)字節(jié)數(shù):00 02 即0X0200,512字節(jié) 偏移0DH:每簇扇區(qū)數(shù):08即每簇包括8個(gè)扇區(qū) 偏移0EH:保留扇區(qū)數(shù):24 00即保留36個(gè)扇區(qū) 偏移10H:FAT表份數(shù):02即兩個(gè)FAT表 偏移11H:未用:00 00 偏移13H:未用:00 00 偏移15H:介質(zhì)類型:F8即本地硬盤 偏移16H:未用:00 00 偏移18H:每磁道扇區(qū)數(shù):3F 00 即每磁道63扇區(qū) 偏移1AH:磁頭數(shù):FF 00即255個(gè)磁頭 偏移1CH:隱藏扇區(qū)數(shù):80 1F即8064個(gè)隱藏扇區(qū) 偏移20H:磁盤總扇區(qū)數(shù) 80 F0 77 00即總共7860352個(gè)扇區(qū)(7860352*512=4024500224,因?yàn)槲业腢盤是4G) 偏移24H:52字節(jié)的擴(kuò)展分區(qū)參數(shù)塊(擴(kuò)展BPB),細(xì)分如下: 偏移24H:FAT表占用扇區(qū)數(shù):EE 1D 00 00即FAT表占7662個(gè)扇區(qū) 偏移28H:未用:00 00 00 00 偏移2CH:根目錄入口簇號(hào):02 00 00 00即根目錄從02號(hào)簇開始 偏移30H:文件系統(tǒng)信息扇區(qū)號(hào):01 00即扇區(qū)1 偏移32H:備份引導(dǎo)扇區(qū)的位置 06 00即6號(hào)扇區(qū)(第7個(gè)扇區(qū)),從WINHEX中我們也可以看到,6號(hào)扇區(qū)的內(nèi)容和0號(hào)引導(dǎo)扇區(qū)內(nèi)容是一樣的 偏移34H:未用:00 00 00 00 00 00 00 00 00 00 00 00 偏移40H:物理磁盤號(hào):00 偏移41H:未用:00 偏移42H:擴(kuò)展引導(dǎo)標(biāo)志 29即0X29 偏移43H:磁盤序列號(hào)F1 2A 27 04通常為一隨機(jī)數(shù) 偏移47H:卷標(biāo)ASCII 4E 4F 20 4E 41 4D 45 20 20 20 20 即NO NAME 偏移52H:文件系統(tǒng)格式ASCII 46 41 54 33 32 20 20 20即FAT32 偏移5AH:分區(qū)引導(dǎo)代碼 420字節(jié): :33C98ED1BCF47B8EC18ED9BD007C884E028A5640B408CD137305B9FFFF8AF166 0FB6C640660FB6D180E23FF7E286CDC0ED0641660FB7C966F7E1668946F8837E1 6007538837E2A007732668B461C6683C00CBB0080B90100E82B00E94803A0FA7DB 47D8BF0AC84C074173CFF7409B40EBB0700CD10EBEEA0FB7DEBE5A0F97DEBE0 98CD16CD196660663B46F80F824A00666A0066500653666810000100807E02000F8 52000B441BBAA558A5640CD130F821C0081FB55AA0F851400F6C1010F840D00FE4 602B4428A56408BF4CD13B0F96658665866586658EB2A6633D2660FB74E1866F7F1 FEC28ACA668BD066C1EA10F7761A86D68A56408AE8C0E4060ACCB80102CD13666 10F8254FF81C300026640490F8571FFC34E544C445220202020202000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000 00000000000000D0A52656D6F7665206469736B73206F72206F74686572206D656469 612EFF0D0A4469736B206572726F72FF0D0A507265737320616E79206B657920746F2 0726573746172740D0A0000000000ACCBD80000 偏移1FEH:有效扇區(qū)結(jié)束標(biāo)志 55 AA 到此分區(qū)引導(dǎo)扇區(qū)介紹結(jié)束。 文件分配表FAT 簡(jiǎn)介: FAT表(文件分配表),是FAT文件系統(tǒng)中用于磁盤數(shù)據(jù)索引和定位而引進(jìn)的一種鏈?zhǔn)浇Y(jié)構(gòu)。在FAT文件系統(tǒng)中,文件的存儲(chǔ)依照FAT表制定的簇鏈?zhǔn)綌?shù)據(jù)結(jié)構(gòu)來進(jìn)行。同時(shí),F(xiàn)AT文件系統(tǒng)將組織數(shù)據(jù)時(shí)使用的目錄也抽象為文件,以簡(jiǎn)化對(duì)數(shù)據(jù)的管理。 FAT1表位置的定位: 在我們前面介紹分區(qū)引導(dǎo)記錄的時(shí)候提到,在偏移0EH處存儲(chǔ)了保留扇區(qū)的個(gè)數(shù),這個(gè)保留扇區(qū)數(shù)指的就是當(dāng)前分區(qū)內(nèi)DBR到FAT表之間的所有扇區(qū)的個(gè)數(shù)(包括DBR但不包括FAT表)。因此,我們可以定位FAT表所在的起始偏移位置了,即24H*200H=4800H。我們貼出4800H處得部分內(nèi)容如下: 顯然沒有錯(cuò),這就是我們FAT1所存儲(chǔ)的位置,只是當(dāng)前沒有存儲(chǔ)文件,所以FAT比較簡(jiǎn)單罷了。 FAT2表位置的定位: 在我們前面介紹分區(qū)引導(dǎo)記錄的時(shí)候提到,在偏移24H處存儲(chǔ)了FAT表所占用的扇區(qū)個(gè)數(shù),我們又知道FAT2是緊鄰FAT1的,所以可以很容易得到FAT2的存儲(chǔ)位置的偏移地址:FAT1的起始偏移地址+FAT1的大小=4800H+1DEEH*200H=3C2400H,我們貼出3C2400H處的部分內(nèi)容如下: 顯然沒有錯(cuò),這就是我們FAT2所存儲(chǔ)的位置,內(nèi)容與FAT1相同。 FAT表的特性: FAT表由一系列大小相等的FAT表項(xiàng)組成,它有如下特性: FAT32中每個(gè)簇的簇地址,使用32bit(4個(gè)字節(jié))記錄在FAT表中。FAT表中的所有字節(jié)位置以4個(gè)字節(jié)為單位進(jìn)行劃分,并對(duì)所有劃分后的位置由0進(jìn)行地址編號(hào)。0 號(hào)地址與1號(hào)地址被系統(tǒng)保留并存儲(chǔ)特殊標(biāo)志內(nèi)容。從2號(hào)地址開始,每個(gè)地址對(duì)應(yīng)于數(shù)據(jù)區(qū)的簇號(hào),F(xiàn)AT表中的地址編號(hào)與數(shù)據(jù)區(qū)中的簇號(hào)相同。我們稱FAT中的這些地址為FAT表項(xiàng),F(xiàn)AT表項(xiàng)中記錄的值稱為FAT表項(xiàng)值。 當(dāng)文件系統(tǒng)被創(chuàng)建,也就是進(jìn)行格式化操作時(shí),分配給FAT區(qū)域的空間將會(huì)被清空,在FAT1與FAT2的0號(hào)表項(xiàng)與1號(hào)表項(xiàng)寫入特定值。由于創(chuàng)建文件系統(tǒng)的同時(shí)也會(huì)創(chuàng)建根目錄,也就是為根目錄分配了一個(gè)簇空間,通常為2號(hào)簇,所以2號(hào)簇所對(duì)應(yīng)的2號(hào)FAT表項(xiàng)也會(huì)被寫入一個(gè)結(jié)束標(biāo)記。 如果某個(gè)簇未被分配使用,它所對(duì)應(yīng)的FAT表項(xiàng)內(nèi)的FAT表項(xiàng)值即用0進(jìn)行填充,表示該FAT表項(xiàng)所對(duì)應(yīng)的簇未分配使用。 當(dāng)某個(gè)簇已被分配使用時(shí),則它對(duì)應(yīng)的FAT表項(xiàng)值也就是該文件的下一個(gè)存儲(chǔ)位置的簇號(hào)。如果該文件結(jié)束于該簇,則在它的FAT表項(xiàng)中記錄的是一個(gè)文件結(jié)束標(biāo)記,對(duì)于FAT32而言,代表文件結(jié)束的FAT表項(xiàng)值為0x0FFFFFFF。 如果某個(gè)簇存在壞扇區(qū),則整個(gè)簇會(huì)用FAT表項(xiàng)值0x0FFFFFF7標(biāo)記為壞簇,不再使用,這個(gè)壞簇標(biāo)記就記錄在它所對(duì)應(yīng)的FAT表項(xiàng)中。 由于簇號(hào)起始于2,所以FAT表的0號(hào)表項(xiàng)與1號(hào)表項(xiàng)不與任何簇對(duì)應(yīng)。FAT32的0號(hào)表項(xiàng)值總是“F8FFFF0F”。1號(hào)表項(xiàng)可能被用于記錄臟標(biāo)志,以說明文件系統(tǒng)沒有被正常卸載或者磁盤表面存在錯(cuò)誤。不過此值似乎并不重要,因此我們只要了解就可以。正常情況下,1號(hào)表項(xiàng)值為“FFFFFFFF”或“FFFFFF0F"。 在文件系統(tǒng)中新建文件時(shí),如果新建的文件只占用一個(gè)簇,為其分配的簇所對(duì)應(yīng)的FAT表項(xiàng)將會(huì)被寫入結(jié)束標(biāo)記。如果新建的文件不只占用一個(gè)簇,則在其所占用的每個(gè)簇對(duì)應(yīng)的FAT表項(xiàng)中寫入為其分配的下一簇的簇號(hào),在最后一個(gè)簇對(duì)應(yīng)的FAT表項(xiàng)中寫入結(jié)束標(biāo)記。 新建目錄時(shí),只為其分配一個(gè)簇的空間,對(duì)應(yīng)的FAT表項(xiàng)中寫入結(jié)束標(biāo)記。當(dāng)目錄增大超出一個(gè)簇的大小時(shí),將會(huì)在空閑空間中繼續(xù)為其分配一個(gè)簇,并在FAT表中為其建立FAT表鏈以描述它所占用的簇情況。 對(duì)文件或目錄進(jìn)行刪除操作時(shí),它們所對(duì)應(yīng)的FAT表項(xiàng)將會(huì)被清空,設(shè)置為0以表示其所對(duì)應(yīng)的簇處于未分配狀態(tài)。 根目錄區(qū) 簡(jiǎn)介: 在FAT32文件系統(tǒng)中,根目錄的位置不再硬性地固定,可以存儲(chǔ)在分區(qū)內(nèi)可尋址的任意簇內(nèi),不過通常根目錄是最早建立的(格式化就生成了)目錄表。所以,我們看到的情況基本上都是根目錄首簇緊鄰FAT2,占簇區(qū)順序上的第1個(gè)簇(即2號(hào)簇)。同時(shí),F(xiàn)AT32文件系統(tǒng)將根目錄當(dāng)做普通的數(shù)據(jù)文件來看,所有沒有了目錄項(xiàng)數(shù)的限制,在需要的時(shí)候可以分配空簇,存儲(chǔ)更多的目錄項(xiàng)。 起始偏移地址定位: 根目錄起始扇區(qū)=保留扇區(qū)數(shù)+FAT×2+(起始簇-2)x每簇的扇區(qū)數(shù),在我們前面介紹分區(qū)引導(dǎo)記錄的時(shí)候提到,偏移2CH處保存了根目錄起始簇號(hào)是2,所以求得根目錄起始扇區(qū)是24H+1DEEH*2H+(2-2)*8H=3C00H,即求得偏移地址3C00H*200H=780000H,我們貼出780000H處的部分內(nèi)容如下: 目錄區(qū)的一個(gè)目錄項(xiàng)占用32個(gè)字節(jié),可以是長(zhǎng)文件名目錄項(xiàng)、文件目錄項(xiàng)、子目錄項(xiàng)等。 短文件名格式的目錄項(xiàng) 對(duì)于短文件名格式的目錄項(xiàng)。其參數(shù)意義如下: 根據(jù)參數(shù)定義,我們來分析一下上圖的目錄項(xiàng) 54 45 53 54 5F 46 41 54 33 32 20 08 00 00 00 00 00 00 00 00 00 00 19 95 10 3F 00 00 00 00 00 00。其中起始11字節(jié)54 45 53 54 5F 46 41 54 33 32 20 是卷標(biāo)TEST_FAT32;第12字節(jié)08指示當(dāng)前目錄項(xiàng)保存的是卷標(biāo);第23-24字節(jié)19 95即9519H,是最近修改時(shí)間:19點(diǎn)40分50秒;第25-26字節(jié)10 3F即3F10H,是最近修改日期:2011年8月16日; 長(zhǎng)文件名格式的目錄項(xiàng) 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)來記錄和編輯,并隱藏起短文件名。 當(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。 長(zhǎng)文件名的實(shí)現(xiàn)有賴于目錄項(xiàng)第12字節(jié)屬性字節(jié),當(dāng)此字節(jié)的值為0FH時(shí),支持長(zhǎng)文件名的系統(tǒng)會(huì)將其當(dāng)做長(zhǎng)文件名的依據(jù),而只支持短文件名的系統(tǒng)會(huì)認(rèn)為是異常而忽略掉。系統(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ù)2字節(jié)的空間。其目錄項(xiàng)定義如: 下面是我建立的長(zhǎng)文件名文件夾abcdefghijklmnopqrstuvwxyz1234567890的目錄項(xiàng): 前面已經(jīng)基于一個(gè)格式化的空U盤分析了一下FAT32文件系統(tǒng)存儲(chǔ)的組織結(jié)構(gòu),下面我們從文件操作的角度來分析一下文件系統(tǒng)的運(yùn)作機(jī)制。由于換了個(gè)U盤,所以仍然貼出剛格式化的空U盤的幾個(gè)重要的數(shù)據(jù)區(qū)如下: 我們可以看出,在分區(qū)格式化的時(shí)候,系統(tǒng)將卷標(biāo)TEST_FAT32存儲(chǔ)在2號(hào)簇,即跟目錄區(qū),如上面根目錄貼圖所示。同時(shí),在FDT區(qū)2號(hào)簇標(biāo)記位置寫入了文件結(jié)束符FF FF FF 0F。顯然,F(xiàn)AT32文件系統(tǒng)將目錄當(dāng)做普通文件來處理的。 下面我們?cè)诟夸浵滦陆ㄒ粋€(gè)文件夾TEST1,看會(huì)有什么變化: 建立了TEST1文件夾后,F(xiàn)DT變成如下: 根目錄變成如下: 重新分配了3號(hào)簇: 從上面的變化可以直觀的看出,系統(tǒng)在新建文件夾時(shí)完成了如下動(dòng)作: a.在父目錄所在簇上建立新的目錄項(xiàng),存儲(chǔ)當(dāng)前所建文件夾信息。 b.分配一個(gè)新簇,給新建的文件夾建立兩個(gè)目錄項(xiàng):父目錄和當(dāng)前目錄。 c.在FDT表中新分配的簇對(duì)應(yīng)的位置上寫下文件結(jié)束符。 d.建立各部分的鏈路關(guān)系:新建文件夾所對(duì)應(yīng)的目錄項(xiàng)的文件起始簇號(hào)字段寫上新分配簇的簇號(hào),新簇上的兩個(gè)目錄項(xiàng)的文件起始簇號(hào)字段分配寫上父目錄所在簇號(hào)(此處是0,本來我以為是2,即根目錄所在簇,不知道為什么,可能特地用0指示根目錄吧)和當(dāng)前簇號(hào)(此處是3)。 為了驗(yàn)證我們上面分析的正確性,我們?cè)僭赥EST1文件夾下建立新文件夾TEST11,看是否做了如下操作: a.在父目錄(即TEST1)所在簇(即3號(hào)簇)上建立新的目錄項(xiàng),存儲(chǔ)TEST11文件夾信息。 b.分配一個(gè)新簇(應(yīng)該是4號(hào)簇),給新建的文件夾(即TEST11)建立兩個(gè)目錄項(xiàng):父目錄和當(dāng)前目錄。 c.在FDT表中新分配的簇(應(yīng)該是4號(hào)簇)對(duì)應(yīng)的位置上寫下文件結(jié)束符。 d.建立各部分的鏈路關(guān)系:新建文件夾(即TEST11)所對(duì)應(yīng)的目錄項(xiàng)的文件起始簇號(hào)字段寫上新分配簇的簇號(hào)(應(yīng)該是4號(hào)簇),,新簇上的兩個(gè)目錄項(xiàng)的文件起始簇號(hào)字段分配寫上父目錄所在簇號(hào)(3號(hào)簇)和當(dāng)前簇號(hào)(應(yīng)該是4號(hào)簇)。 新建TEST11文件夾后FDT變成: 根目錄沒有變化: 3號(hào)簇變成: 新分配4號(hào)簇: 顯然我們的估計(jì)沒有錯(cuò)的,也進(jìn)一步證明我們前面的分析是正確的。 下面我們?cè)俜治鼋⑽募那闆r 我們先建立一個(gè)100字節(jié)的文件TEST.TXT,然后把這個(gè)文件拷貝到U盤的根目錄下,F(xiàn)DT變成如下: 根目錄變成: 新分配5號(hào)簇保存文件內(nèi)容: 從上面的變化可以直觀的看出,系統(tǒng)新建文件和新建文件夾所完成的操作是一樣一樣的: a.在父目錄所在簇上建立新的目錄項(xiàng),存儲(chǔ)當(dāng)前所建文件信息。 b.分配一個(gè)新簇,存儲(chǔ)新建的文件的內(nèi)容。 c.在FDT表中新分配的簇對(duì)應(yīng)的位置上寫下文件結(jié)束符。 d.建立鏈路關(guān)系:新建文件所對(duì)應(yīng)的目錄項(xiàng)的文件起始簇號(hào)字段寫上新分配簇的簇號(hào)。 結(jié)束總結(jié): 1.在FAT32文件系統(tǒng)中,目錄和文件的存儲(chǔ)采用統(tǒng)一的方式。 2.文件系統(tǒng)的操作的單位是簇,每新建立一個(gè)文件或文件夾,至少會(huì)重新分配一個(gè)簇號(hào)。 3.如果一個(gè)文件或目錄的內(nèi)容要多個(gè)簇才能存儲(chǔ)得下,則系統(tǒng)會(huì)分配多個(gè)簇來存儲(chǔ)文件或目錄的內(nèi)容 4.當(dāng)需要多個(gè)簇時(shí),這些簇可能連續(xù)也可能不連續(xù),但無(wú)論是連續(xù)或是不連續(xù),系統(tǒng)都是采用FDT鏈表的形式來組織的。 FAT32系統(tǒng)中長(zhǎng)文件名的存儲(chǔ)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)來記錄和編輯,并隱藏起短文件名。 當(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è)字母。通過數(shù)學(xué)操縱長(zhǎng)文件名的剩余字母生成短文件名的后四個(gè)字母,然后加后綴"~1"直到最后(如果有必要,或是其他數(shù)字以避免重復(fù)的文件名)。 (4)、如果存在老OS或程序無(wú)法讀取的字符,換以"_" 短文件格式的目錄項(xiàng)。其參數(shù)意義見表14:
長(zhǎng)文件名的實(shí)現(xiàn)有賴于目錄項(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通常支持不超過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。
系統(tǒng)在存儲(chǔ)長(zhǎng)文件名時(shí),總是先按倒序填充長(zhǎng)文件名目錄項(xiàng),然后緊跟其對(duì)應(yīng)的短文件名。從表15可以看出,長(zhǎng)文件名中并不存儲(chǔ)對(duì)應(yīng)文件的文件開始簇、文件大小、各種時(shí)間和日期屬性。文件的這些屬性還是存放在短文件名目錄項(xiàng)中,一個(gè)長(zhǎng)文件名總是和其相應(yīng)的短文件名一一對(duì)應(yīng),短文件名沒有了長(zhǎng)文件名還可以讀,但長(zhǎng)文件名如果沒有對(duì)應(yīng)的短文件名,不管什么系統(tǒng)都將忽略其存在。所以短文件名是至關(guān)重要的。 在不支持長(zhǎng)文件名的環(huán)境中對(duì)短文件名中的文件名和擴(kuò)展名字段作更改(包括刪除,因?yàn)閯h除是對(duì)首字符改寫E5H),都會(huì)使長(zhǎng)文件名形同虛設(shè)。 (長(zhǎng)文件名如何與短文件名對(duì)應(yīng)??jī)H靠她們之間的位置關(guān)系?) 長(zhǎng)文件名和短文件名之間的聯(lián)系光靠他們之間的位置關(guān)系維系顯然遠(yuǎn)遠(yuǎn)不夠。其實(shí),長(zhǎng)文件名的0xD字節(jié)的校驗(yàn)和起很重要的作用,此校驗(yàn)和是用短文件名的11個(gè)字符通過一種運(yùn)算方式來得到的。系統(tǒng)根據(jù)相應(yīng)的算法來確定相應(yīng)的長(zhǎng)文件名和短文件名是否匹配。這個(gè)算法不太容易用公式說明,我們用一段c程序來加以說明。 假設(shè)文件名11個(gè)字符組成字符串shortname[],校驗(yàn)和用chknum表示。得到過程如下: int i,j,chknum=0; for (i=11; i>0; i--) chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; 如果通過短文件名計(jì)算出來的校驗(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ù)的讀取便游刃有余了。 本文出自數(shù)據(jù)恢復(fù)網(wǎng)(www.),疏漏在所難免,希望指正。若需轉(zhuǎn)載請(qǐng)保留此信息;若需修改,請(qǐng)用以下方式與作者取得聯(lián)系 3、sjhf@ FAT文件系統(tǒng)總結(jié)MBR:Master Boot Record (主引導(dǎo)記錄) DBR:DOS Boot Record (DOS引導(dǎo)記錄,位于分區(qū)引導(dǎo)扇區(qū)) BPB:BIOS Parameter Block (BIOS參數(shù)塊) FAT:File Allocation Table (文件分配表) Sector:扇區(qū) Cluster:簇 一、硬盤組織結(jié)構(gòu) 下面是一個(gè)包含 4 個(gè)分區(qū)的硬盤結(jié)構(gòu)示意圖,其中分為 3 個(gè)基本分區(qū)和一個(gè)擴(kuò)展分區(qū)。 二、FAT文件系統(tǒng)結(jié)構(gòu) FAT 文件系統(tǒng)是由按照如下順序排列的幾個(gè)部分組成的: 0 – Reserved Region 1 – FAT Region 2 – Root Directory Region (FAT32沒有這部分) 3 – File and Directory Data Region
FAT 系統(tǒng)的數(shù)據(jù)存儲(chǔ)采用小端(Little Endian)方式,注意到這一點(diǎn)很重要,在使用大 端(Big Endian)的系統(tǒng)中,讀取多字節(jié)數(shù)據(jù)的時(shí)候必須要經(jīng)過轉(zhuǎn)換,否則,讀取到的數(shù)據(jù)是不正確的。 例如:一個(gè) 32-bit 數(shù)據(jù) 0x12345678 在 FAT 中的保存方式如下圖所示: 三、主引導(dǎo)扇區(qū) 硬盤主引導(dǎo)扇區(qū) = 硬盤主引導(dǎo)記錄(MBR)+硬盤分區(qū)表(DPT) MBR:扇區(qū)內(nèi)偏移地址 0 ~ 0x1BD DPT:扇區(qū)內(nèi)偏移地址 0x1BE ~ 0x1FD,其中又分為 4 個(gè)分區(qū)表: 第一個(gè)分區(qū)表:0x1BE ~ 0x1CD 第二個(gè)分區(qū)表:0x1CE ~ 0x1DD 第三個(gè)分區(qū)表:0x1DE ~ 0x1ED 第四個(gè)分區(qū)表:0x1EE ~ 0x1FD 每個(gè)分區(qū)表的信息如下表所示:
分區(qū)標(biāo)志類型值及其含義
主引導(dǎo)扇區(qū) 上面是從一張 SD 卡讀到的主引導(dǎo)扇區(qū)信息??梢钥闯?,MBR 區(qū)域數(shù)據(jù)全部為 0,這張 SD 卡只有一個(gè)分區(qū),這個(gè)分區(qū)前的扇區(qū)數(shù)為 0x0000003F,所以這個(gè)分區(qū)的開始位置就是扇區(qū)0x0000003F,總扇區(qū)數(shù)為 0x000F1EC1(990913 個(gè)扇區(qū))。 四、分區(qū)引導(dǎo)扇區(qū) 也常常稱為啟動(dòng)扇區(qū),Microsoft稱它為 0 扇區(qū)(0th sector),通過前面的介紹我們知 道,稱它為 0 扇區(qū)其實(shí)是不正確的,這樣容易讓人誤解它為磁盤的最前面一個(gè)扇區(qū),稱它為 0 扇區(qū)只是表明它是FAT中扇區(qū)的參考點(diǎn)而已。 該扇區(qū)中包含有我們關(guān)注的一個(gè)重要數(shù)據(jù)結(jié)構(gòu) BPB(BIOS Parameter Block)。以下表 格內(nèi)容翻譯自 Microsoft 的《Microsoft Extensible Firmware Initiative FAT32 File System Specification—version1.03》,其中包含 BPB 各項(xiàng)的描述。 NOTE:在以下的敘述中,名字以 BPB_開頭的屬于 BPB 部分,以 BS 開頭的屬于啟動(dòng)扇區(qū)(Boot Sector)部分,實(shí)際上并不屬于BPB。
FAT32 的 BPB 的內(nèi)容和 FAT12/16 的內(nèi)容在地址 0x36 以前是完全一樣的,從偏移量 0x36開始,他們的內(nèi)容有所區(qū)別,具體的內(nèi)容要看 FAT 類型為 FAT12/16 還是 FAT32,這點(diǎn)保證了 在啟動(dòng)扇區(qū)中包含一個(gè)完整的 FAT12/16 或 FAT32 的 BPB 的內(nèi)容,這么做是為了達(dá)到最好的兼容性,同時(shí)也為了保證所有的 FAT 文件系統(tǒng)驅(qū)動(dòng)程序能正確的識(shí)別和驅(qū)動(dòng)不同的 FAT 格式,并 讓他們良好地工作,因?yàn)樗麄儼爽F(xiàn)有的全部?jī)?nèi)容從 offset 36 開始 FAT12/FAT16 的內(nèi)容開始區(qū)別于 FAT32,下面分兩個(gè)表格列出,下 表為 FAT12/FAT16 的內(nèi)容下表為 FAT32 的內(nèi)容
關(guān)于 FAT 啟動(dòng)扇區(qū)還有一點(diǎn)重要的說明,我們假設(shè)里面的內(nèi)容是按字節(jié)排序的,那么扇區(qū)[510]的內(nèi)容一定 0x55,扇區(qū)[511]的內(nèi)容一定是 0xAA很多 FAT 資數(shù)文檔會(huì)把 0xAA55 說成是“啟動(dòng)扇區(qū)最后兩字節(jié)的內(nèi)容”,這樣的說法是正 確的,但僅僅適用于 BPB_BytsPerSec 值為 512 的情況。若 BPB_BytsSec 的值大于 512,該標(biāo)記的位置并沒有改變,雖然在啟動(dòng)扇區(qū)的最后兩個(gè)字節(jié)寫 0xAA55 并沒有問題。 五、FAT類型識(shí)別 FAT 的字類型(FAT12/16/32)只能通過 FAT 卷中的簇(Cluster)數(shù)來判定,沒有其 他的辦法。 Cluster 總數(shù)的計(jì)算:RootDirSectors = (BPB_RootEntCnt*32) /BPB_BytsPerSec DataSect = TotSec – (BPB_RsvdSecCnt +(BPB_NumFATs * FATSz) + RootDirSectors) CountofClusters = DataSec / BPB_SecPerClus If(CountofClusters < 4085) { /*卷類型是 FAT12 */ } else if(CountofClusters < 65525) { /* 卷類型是 FAT16 */ } else { /* 卷類型是 FAT32 */ } 注意這里的簇?cái)?shù)(count of Cluster)是指數(shù)據(jù)區(qū)所占簇的數(shù)量(the count of the data cluster),從簇 2 算起,而“最大可用簇?cái)?shù)”(Maximun valid cluster number for the volume)是 CountofClusters +1,“包括保留簇的簇?cái)?shù)”(count of cluster including the two reserved cluster)則為CountofClusters +2。根目錄占據(jù)的 Sector 數(shù):RootDirSectors = (BPB_RootEntCnt*32) /BPB_BytsPerSec 數(shù)據(jù)區(qū)(Cluster 2)的起始 Sector: FirstDataSector = BPB_EsvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors 給一個(gè)合法的簇號(hào) N,該簇的第一個(gè)扇區(qū)號(hào)由下式計(jì)算:FirstSectorofCluster =((N -2) * BPB_SecPerClust) + FirstDataSecot; 因?yàn)?BPB_SecPerClus 總是 2 的整數(shù)次方,這意味著 BPB_SecPerSlus 的乘法運(yùn)算可 以通過移動(dòng)來進(jìn)行。 NOTE:這里所說的 Sector 號(hào),指的是針對(duì)卷中包 BPB 的第一個(gè)扇區(qū)(DBR)的偏移量(DBR設(shè)為Sector 0)。 六、FAT各部分位置的計(jì)算 DBR_Base:從DPT中偏移8Bytes的地址讀取4Bytes數(shù)據(jù)就可以直接看作是DBR所在的 Sector。 RsvSectors = BPB_RsvdSecCnt。 FAT_Base = DBR_Base + RsvSectors FATSize = BPB_NumFATs * FATSz 其中,F(xiàn)ATSz = (FAT32?) BPB_FATSz32 : BPB_FATSz16 Root_Base:如果是FAT12/FAT16,則Root_Base = FAT_Base + FATSize 如果是FAT32,則Root_Base = BPB_RootClus RootSize :如果是FAT32,則沒有限制;否則RootSize = (BPB_RootEntCnt*32) / BPB_BytsPerSec Data_Base:僅對(duì)于FAT12/FAT16,Data_Base = Root_Base + RootSize 七、FAT表結(jié)構(gòu) FAT 表(File Alloacation Table)是一一對(duì)應(yīng)于數(shù)據(jù)簇號(hào)的列表。文件系統(tǒng)分配磁盤空間按簇來分配。因此,文件占有磁盤空間時(shí),基本單位不是字節(jié)而是簇, 即使某個(gè)文件只有一個(gè)字節(jié),操作系統(tǒng)也會(huì)給它分配一個(gè)最小單元:即一個(gè)簇。為了可以將磁盤 空間有序地分配給相應(yīng)的文件,而讀取文件的時(shí)候又可以從相應(yīng)的地址讀出文件,我們可以把數(shù) 據(jù)區(qū)空間分成 BPB_BytsPerSec*BPB_SecPerClus 字節(jié)長(zhǎng)的簇來管理,F(xiàn)AT 表項(xiàng)的大小與 FAT 表的類型有關(guān),F(xiàn)AT12 的表項(xiàng)為 12bit ,F(xiàn)AT16 為 16bit, 而 FAT32 則為 32bit。對(duì) 于大文件,需要分配多個(gè)簇。同一個(gè)文件的數(shù)據(jù)并不一定完整地存放在磁盤中一個(gè)連續(xù)地區(qū)域 內(nèi),而往往會(huì)分若干段,像鏈子一樣存放。這種存儲(chǔ)方式稱為文件的鏈?zhǔn)酱鎯?chǔ)。為了實(shí)現(xiàn)文件的 鏈?zhǔn)酱鎯?chǔ),文件系統(tǒng)必須準(zhǔn)確地記錄哪些簇已經(jīng)被文件占用,還必須為每個(gè)已經(jīng)占用的簇指明存 儲(chǔ)后繼內(nèi)空的下一個(gè)簇的簇號(hào),對(duì)于文件的最后一簇,則要指明本簇?zé)o后繼簇。這些都是由 FAT 表來保存的,F(xiàn)AT 表的對(duì)應(yīng)表項(xiàng)中記錄著它所代表的簇的有關(guān)信息:諸如是空,是不是壞簇,是 否是已經(jīng)是某個(gè)文件的尾簇等。 以 FAT16 為例說明 FAT 的結(jié)構(gòu)如下:
FAT各系統(tǒng)記錄項(xiàng)的取值含義(16進(jìn)制)
八、長(zhǎng)文件名 長(zhǎng)文件名是在原有的 FAT 系統(tǒng)上引入的,在只支持短文件名的系統(tǒng)上,長(zhǎng)文件名就像是不存在一樣。為了達(dá)到這個(gè)目標(biāo),長(zhǎng)文件名通過在原有的目錄項(xiàng)中引入新的屬性字(Attribute)得以實(shí)現(xiàn)。 ATTR_LONG_NAME = ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID 判斷一個(gè)目錄項(xiàng)是否為長(zhǎng)文件名,要通過下面 MASK 實(shí)現(xiàn): ATTR_LONG_NAME_MASK = ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY | ATTR_ARCHIVE 長(zhǎng)文件名目錄項(xiàng)數(shù)據(jù)結(jié)構(gòu)如下:
長(zhǎng)文件名字符采用 Unicode 編碼。 Checksum 算法,用 C 語(yǔ)言實(shí)現(xiàn)如下: //------------------------------------------------------------------------ //ChkSum() //Returns an unsigned byte checksum computed on an unsigned byte //array. The array must be 11 bytes long and is assumed to contain //a name stored in the format of a MS-DOS directory entry. // Passed: pFcbName Pointer to an unsigned byte array assumed to be 11 bytes long. // Returns: Sum An 8-bit unsigned checksum of the array pointed // to by pFcbName. unsigned char ChkSum (unsigned char *pFcbName) { short FcbNameLen; unsigned char Sum; Sum = 0; for (FcbNameLen=11; FcbNameLen!=0; FcbNameLen--) { // NOTE: The operation is an unsigned char rotate right Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *pFcbName++; } return (Sum); } 下面是一組長(zhǎng)文件名目錄項(xiàng)。 00 79 96 40 43 70 00 71 00 72 00 73 00 74 00 0F 00 52 2E 00 ...Cp.q.r.s.t R.. 00 79 96 50 74 00 78 00 74 00 00 00 FF FF 00 00 FF FF FF FF t.x.t...…… 00 79 96 60 02 63 00 64 00 65 00 66 00 67 00 0F 00 52 68 00 .c.d.e.f.g...Rh. 00 79 96 70 69 00 67 00 6B 00 6C 00 6D 00 00 00 6E 00 6F 00 i.g.k.l.m...n.o. 00 79 96 80 01 73 00 75 00 62 00 64 00 69 00 0F 00 52 72 00 .s.u.b.d.i...Rr. 00 79 96 90 66 00 69 00 6C 00 65 00 5F 00 00 00 61 00 62 00 f.i.l.e._...a.b. 00 79 96 A0 53 55 42 44 49 52 7E 31 54 58 54 20 00 22 2E 4F SUBDIR~1TXT .".O 00 79 96 B0 6C 3B 71 3B 00 00 E9 84 6D 3B 14 00 00 0E 00 00 l;q;..閯 m;...... 可以看出,長(zhǎng)文件名為“subdirfile_abcdefghigklmnopqrst.txt”,對(duì)應(yīng)的短文件 名為“SUBDIR~1.TXT”。 下面是《Microsoft Extensible Firmware Initiative FAT32 File System Specification—version1.03》中給出的示例: 假設(shè)創(chuàng)建一個(gè)名為“The quick brown.fox”的文件,系統(tǒng)將為它建立如下的目錄項(xiàng): 九、目錄結(jié)構(gòu) 目錄所在的扇區(qū),都是以32 Bytes 劃分為一個(gè)單位,每個(gè)單位稱為一個(gè)目錄項(xiàng)(Directory Entry),即每個(gè)目錄項(xiàng)的長(zhǎng)度都是 32 Bytes。 FAT32短文件目錄項(xiàng)32個(gè)字節(jié)的表示定義FAT32 表每簇占用 4 Bytes,從 Sector 內(nèi)偏移地址 50 讀取 4 Bytes 數(shù)據(jù)為 0x15,表 示之后的數(shù)據(jù)占用簇0x15,簇0x15 在Sector 內(nèi)偏移地址為0x54,從地址0x54 讀取4 Bytes。數(shù)據(jù)為 0x16,依次類推,最后在偏移地址 0x68 讀取 4 Bytes 數(shù)據(jù)為 0x0FFFFFFF,表示文 件在該簇就結(jié)束了。所以該文件占用的簇號(hào)依次為 0x14,0x15,0x16,0x17,0x18,0x19 和 0x20。 |
|