硬盘 FAT 文件系统原理的详细分析.docx
《硬盘 FAT 文件系统原理的详细分析.docx》由会员分享,可在线阅读,更多相关《硬盘 FAT 文件系统原理的详细分析.docx(44页珍藏版)》请在冰豆网上搜索。
硬盘FAT文件系统原理的详细分析
一、硬盤的物理結構:
硬盤存儲數據是根據電、磁轉換原理實現的。
硬盤由一個或幾個表面鍍有磁性物質的金屬或玻璃等物質盤片以及盤片兩面所安裝的磁頭和相應的控制電路組成(圖1),其中盤片和磁頭密封在無塵的金屬殼中。
硬盤工作時,盤片以設計轉速高速旋轉,設置在盤片表面的磁頭則在電路控制下徑向移動到指定位置然後將數據存儲或讀取出來。
當系統向硬盤寫入數據時,磁頭中『寫數據』電流產生磁場使盤片表面磁性物質狀態發生改變,並在寫電流磁場消失後仍能保持,這樣數據就存儲下來了;當系統從硬盤中讀數據時,磁頭經過盤片指定區域,盤片表面磁場使磁頭產生感應電流或線圈阻抗產生變化,經相關電路處理後還原成數據。
因此只要能將盤片表面處理得更平滑、磁頭設計得更精密以及盡量提高盤片旋轉速度,就能造出容量更大、讀寫數據速度更快的硬盤。
這是因為盤片表面處理越平、轉速越快就能越使磁頭離盤片表面越近,提高讀、寫靈敏度和速度;磁頭設計越小越精密就能使磁頭在盤片上佔用空間越小,使磁頭在一張盤片上建立更多的磁道以存儲更多的數據。
二、硬盤的邏輯結構:
硬盤由很多盤片(platter)組成,每個盤片的每個面都有一個讀寫磁頭。
如果有N個盤片。
就有2N個面,對應2N個磁頭(Heads),從0、1、2開始編號。
每個盤片被劃分成若乾個同心圓磁道(邏輯上的,是不可見的。
)每個盤片的劃分規則通常是一樣的。
這樣每個盤片的半徑均為固定值R的同心圓再邏輯上形成了一個以電機主軸為軸的柱面(Cylinders),從外至裡編號為0、1、2……每個盤片上的每個磁道又被劃分為幾十個扇區(Sector),通常的容量是512byte,並按照一定規則編號為1、2、3……形成Cylinders×Heads×Sector個扇區。
這三個參數即是硬盤的物理參數。
我們下面的很多實踐需要深刻理解這三個參數的意義。
三、磁盤引導原理:
3.1 MBR(master boot record)扇區:
計算機在按下power鍵以後,開始執行主板bios程序。
進行完一系列檢測和配置以後。
開始按bios中設定的系統引導順序引導系統。
假定現在是硬盤。
Bios執行完自己的程序後如何把執行權交給硬盤呢。
交給硬盤後又執行存儲在哪裡的程序呢。
其實,稱為mbr的一段代碼起著舉足輕重的作用。
MBR(master boot record),即主引導記錄,有時也稱主引導扇區。
位於整個硬盤的0柱面0磁頭1扇區(可以看作是硬盤的第一個扇區),bios在執行自己固有的程序以後就會jump到mbr中的第一條指令。
將系統的控制權交由mbr來執行。
在總共512byte的主引導記錄中,MBR的引導程序佔了其中的前446個字節(偏移0H~偏移1BDH),隨後的64個字節(偏移1BEH~偏移1FDH)為DPT(Disk PartitionTable,硬盤分區表),最後的兩個字節『55 AA』(偏移1FEH~偏移1FFH)是分區有效結束標志。
MBR不隨操作系統的不同而不同,意即不同的操作系統可能會存在相同的MBR,即使不同,MBR也不會夾帶操作系統的性質。
具有公共引導的特性。
我們來分析一段mbr。
下面是用winhex查看的一塊希捷120GB硬盤的mbr。
你的硬盤的MBR引導代碼可能並非這樣。
不過即使不同,所執行的功能大體是一樣的。
這裡找wowocock關於磁盤mbr的反編譯,已加了詳細的注釋,感興趣可以細細研究一下。
我們看DPT部分。
操作系統為了便於用戶對磁盤的管理。
加入了磁盤分區的概念。
即將一塊磁盤邏輯劃分為幾塊。
磁盤分區數目的多少只受限於C~Z的英文字母的數目,在上圖DPT共64個字節中如何表示多個分區的屬性呢?
microsoft通過鏈接的方法解決了這個問題。
在DPT共64個字節中,以16個字節為分區表項單位描述一個分區的屬性。
也就是說,第一個分區表項描述一個分區的屬性,一般為基本分區。
第二個分區表項描述除基本分區外的其餘空間,一般而言,就是我們所說的擴展分區。
這部分的大體說明見表1。
注:
上表中的超過1字節的數據都以實際數據顯示,就是按高位到地位的方式顯示。
存儲時是按低位到高位存儲的。
兩者表現不同,請仔細看清楚。
以後出現的表,圖均同。
也可以在winhex中看到這些參數的意義:
說明:
每個分區表項佔用16個字節,假定偏移地址從0開始。
如圖3的分區表項3。
分區表項4同分區表項3。
1、0H偏移為活動分區是否標志,只能選00H和80H。
80H為活動,00H為非活動。
其餘值對microsoft而言為非法值。
2、重新說明一下(這個非常重要):
大於1個字節的數被以低字節在前的存儲格式格式(little endian format)或稱反字節順序保存下來。
低字節在前的格式是一種保存數的方法,這樣,最低位的字節最先出現在十六進制數符號中。
例如,相對扇區數字段的值0x3F000000的低字節在前表示為0x0000003F。
這個低字節在前的格式數的十進制數為63。
3、系統在分區時,各分區都不允許跨柱面,即均以柱面為單位,這就是通常所說的分區粒度。
有時候我們分區是輸入分區的大小為7000M,分出來卻是6997M,就是這個原因。
偏移2H和偏移6H的扇區和柱面參數中,扇區佔6位(bit),柱面佔10位(bit),以偏移6H為例,其低6位用作扇區數的二進制表示。
其高兩位做柱面數10位中的高兩位,偏移7H組成的8位做柱面數10位中的低8位。
由此可知,實際上用這種方式表示的分區容量是有限的,柱面和磁頭從0開始編號,扇區從1開始編號,所以最多只能表示1024個柱面×63個扇區×256個磁頭×512byte=8455716864byte。
即通常的8.4GB(實際上應該是7.8GB左右)限制。
實際上磁頭數通常只用到255個(由匯編語言的尋址寄存器決定),即使把這3個字節按線性尋址,依然力不從心。
在後來的操作系統中,超過8.4GB的分區其實已經不通過C/H/S的方式尋址了。
而是通過偏移CH~偏移FH共4個字節32位線性扇區地址來表示分區所佔用的扇區總數。
可知通過4個字節可以表示2^32個扇區,即2TB=2048GB,目前對於大多數計算機而言,這已經是個天文數字了。
在未超過8.4GB的分區上,C/H/S的表示方法和線性扇區的表示方法所表示的分區大小是一致的。
也就是說,兩種表示方法是協調的。
即使不協調,也以線性尋址為准。
(可能在某些系統中會提示出錯)。
超過8.4GB的分區結束C/H/S一般填充為FEH FFH FFH。
即C/H/S所能表示的最大值。
有時候也會用柱面對1024的模來填充。
不過這幾個字節是什麼其實都無關緊要了。
雖然現在的系統均采用線性尋址的方式來處理分區的大小。
但不可跨柱面的原則依然沒變。
本分區的扇區總數加上與前一分區之間的保留扇區數目依然必須是柱面容量的整數倍。
(保留扇區中的第一個扇區就是存放分區表的MBR或虛擬MBR的扇區,分區的扇區總數在線性表示方式上是不計入保留扇區的。
如果是第一個分區,保留扇區是本分區前的所有扇區。
附:
分區表類型標志如圖4
3.2 擴展分區
擴展分區中的每個邏輯驅動器都存在一個類似於MBR的擴展引導記錄( Extended Boot Record, EBR),也有人稱之為虛擬mbr或擴展mbr,意思是一樣的。
擴展引導記錄包括一個擴展分區表和該扇區的標簽。
擴展引導記錄將記錄只包含擴展分區中每個邏輯驅動器的第一個柱面的第一面的信息。
一個邏輯驅動器中的引導扇區一般位於相對扇區32或63。
但是,如果磁盤上沒有擴展分區,那麼就不會有擴展引導記錄和邏輯驅動器。
第一個邏輯驅動器的擴展分區表中的第一項指向它自身的引導扇區。
第二項指向下一個邏輯驅動器的EBR。
如果不存在進一步的邏輯驅動器,第二項就不會使用,而且被記錄成一系列零。
如果有附加的邏輯驅動器,那麼第二個邏輯驅動器的擴展分區表的第一項會指向它本身的引導扇區。
第二個邏輯驅動器的擴展分區表的第二項指向下一個邏輯驅動器的EBR。
擴展分區表的第三項和第四項永遠都不會被使用。
通過一幅4分區的磁盤結構圖可以看到磁盤的大致組織形式。
如圖5:
關於擴展分區,如圖6所示,擴展分區中邏輯驅動器的擴展引導記錄是一個連接表。
該圖顯示了一個擴展分區上的三個邏輯驅動器,說明了前面的邏輯驅動器和最後一個邏輯驅動器之間在擴展分區表中的差異。
除了擴展分區上最後一個邏輯驅動器外,表2中所描述的擴展分區表的格式在每個邏輯驅動器中都是重復的:
第一個項標識了邏輯驅動器本身的引導扇區,第二個項標識了下一個邏輯驅動器的EBR。
最後一個邏輯驅動器的擴展分區表只會列出它本身的分區項。
最後一個擴展分區表的第二個項到第四個項被使用。
擴展分區表項中的相對扇區數字段所顯示的是從擴展分區開始到邏輯驅動器中第一個扇區的位移的字節數。
總扇區數字段中的數是指組成該邏輯驅動器的扇區數目。
總扇區數字段的值等於從擴展分區表項所定義的引導扇區到邏輯驅動器末尾的扇區數。
有時候在磁盤的末尾會有剩餘空間,剩餘空間是什麼呢?
我們前面說到,分區是以1柱面的容量為分區粒度的,那麼如果磁盤總空間不是整數個柱面的話,不夠一個柱面的剩下的空間就是剩餘空間了,這部分空間並不參與分區,所以一般無法利用。
照道理說,磁盤的物理模式決定了磁盤的總容量就應該是整數個柱面的容量,為什麼會有不夠一個柱面的空間呢。
在我的理解看來,本來現在的磁盤為了更大的利用空間,一般在物理上並不是按照外圍的扇區大於裡圈的扇區這種管理方式,只是為了與操作系統兼容而抽象出來CHS。
可能其實際空間 zymail@
四、FAT分區原理
先來一幅結構圖:
現在我們著重研究FAT格式分區內數據是如何存儲的。
FAT分區格式是MICROSOFT最早支持的分區格式,依據FAT表中每個簇鏈的所佔位數(有關概念,後面會講到)分為fat12、fat16、fat32三種格式"變種",但其基本存儲方式是相似的。
仔細研究圖7中的fat16和fat32分區的組成結構。
下面依次解釋DBR、FAT1、FAT2、根目錄、數據區、剩餘扇區的概念。
提到的地址如無特別提示均為分區內部偏移。
4.1 關於DBR.
DBR區(DOS BOOT RECORD)即操作系統引導記錄區的意思,通常佔用分區的第0扇區共512個字節(特殊情況也要佔用其它保留扇區,我們先說第0扇)。
在這512個字節中,其實又是由跳轉指令,廠商標志和操作系統版本號,BPB(BIOS Parameter Block),擴展BPB,os引導程序,結束標志幾部分組成。
以用的最多的FAT32為例說明分區DBR各字節的含義。
見圖8。
圖8的對應解釋見表3
圖9給出了winhex對圖8 DBR的相關參數解釋:
根據上邊圖例,我們來討論DBR各字節的參數意義。
MBR將CPU執行轉移給引導扇區,因此,引導扇區的前三個字節必須是合法的可執行的基於x86的CPU指令。
這通常是一條跳轉指令,該指令負責跳過接下來的幾個不可執行的字節(BPB和擴展BPB),跳到操作系統引導代碼部分。
跳轉指令之後是8字節長的OEM ID,它是一個字符串, OEM ID標識了格式化該分區的操作系統的名稱和版本號。
為了保留與MS-DOS的兼容性,通常Windows 2000格式化該盤是在FAT16和FAT32磁盤上的該字段中記錄了『MSDOS 5.0』,在NTFS磁盤上(關於ntfs,另述),Windows 2000記錄的是『NTFS』。
通常在被Windows 95格式化的磁盤上OEM ID字段出現『MSWIN4.0』,在被Windows 95 OSR2和Windows 98格式化的磁盤上OEM ID字段出現『MSWIN4.1』。
接下來的從偏移0x0B開始的是一段描述能夠使可執行引導代碼找到相關參數的信息。
通常稱之為BPB(BIOS Parameter Block),BPB一般開始於相同的位移量,因此,標准的參數都處於一個已知的位置。
磁盤容量和幾何結構變量都被封在BPB之中。
由於引導扇區的第一部分是一個x86跳轉指令。
因此,將來通過在BPB末端附加新的信息,可以對BPB進行擴展。
只需要對該跳轉指令作一個小的調整就可以適應BPB的變化。
圖9已經列出了項目的名稱和取值,為了系統的研究,針對圖8,將FAT32分區格式的BPB含義和擴展BPB含義釋義為表格,見表4和表5。
DBR的偏移0x5A開始的數據為操作系統引導代碼。
這是由偏移0x00開始的跳轉指令所指向的。
在圖8所列出的偏移0x00~0x02的跳轉指令"EB 58 90"清楚地指明了OS引導代碼的偏移位置。
jump 58H加上跳轉指令所需的位移量,即開始於0x5A。
此段指令在不同的操作系統上和不同的引導方式上,其內容也是不同的。
大多數的資料上都說win98,構建於fat基本分區上的win2000,winxp所使用的DBR只佔用基本分區的第0扇區。
他們提到,對於fat32,一般的32個基本分區保留扇區只有第0扇區是有用的。
實際上,以FAT32構建的操作系統如果是win98,系統會使用基本分區的第0扇區和第2扇區存儲os引導代碼;以FAT32構建的操作系統如果是win2000或winxp,系統會使用基本分區的第0扇區和第0xC扇區(win2000或winxp,其第0xC的位置由第0扇區的0xAB偏移指出)存儲os引導代碼。
所以,在fat32分區格式上,如果DBR一扇區的內容正確而缺少第2扇區(win98系統)或第0xC扇區(win2000或winxp系統),系統也是無法啟動的。
如果自己手動設置NTLDR雙系統,必須知道這一點。
DBR扇區的最後兩個字節一般存儲值為0x55AA的DBR有效標志,對於其他的取值,系統將不會執行DBR相關指令。
上面提到的其他幾個參與os引導的扇區也需以0x55AA為合法結束標志。
FAT16 DBR:
FAT32中DBR的含義大致如此,對於FAT12和FAT16其基本意義類似,只是相關偏移量和參數意義有小的差異,FAT格式的區別和來因,以後會說到,此處不在多說FAT12與FAT16。
我將FAT16的扇區參數意義列表。
感興趣的朋友自己研究一下,和FAT32大同小異的。
4.2 關於保留扇區
在上述FAT文件系統DBR的偏移0x0E處,用2個字節存儲保留扇區的數目。
所謂保留扇區(有時候會叫系統扇區,隱藏扇區),是指從分區DBR扇區開始的僅為系統所有的扇區,包括DBR扇區。
在FAT16文件系統中,保留扇區的數據通常設置為1,即僅僅DBR扇區。
而在FAT32中,保留扇區的數據通常取為32,有時候用Partition Magic分過的FAT32分區會設置36個保留扇區,有的工具可能會設置63個保留扇區。
FAT32中的保留扇區除了磁盤總第0扇區用作DBR,總第2扇區(win98系統)或總第0xC扇區(win2000,winxp)用作OS引導代碼擴展部分外,其餘扇區都不參與操作系統管理與磁盤數據管理,通常情況下是沒作用的。
操作系統之所以在FAT32中設置保留扇區,是為了對DBR作備份或留待以後昇級時用。
FAT32中,DBR偏移0x34佔2字節的數據指明了DBR備份扇區所在,一般為0x06,即第6扇區。
當FAT32分區DBR扇區被破壞導致分區無法訪問時。
可以用第6扇區的原備份替換第0扇區來找回數據。
4.3 FAT表和數據的存儲原則
FAT表(File Allocation Table 文件分配表),是Microsoft在FAT文件系統中用於磁盤數據(文件)索引和定位引進的一種鏈式結構。
假如把磁盤比作一本書,FAT表可以認為相當於書中的目錄,而文件就是各個章節的內容。
但FAT表的表示方法卻與目錄有很大的不同。
在FAT文件系統中,文件的存儲依照FAT表制定的簇鏈式數據結構來進行。
同時,FAT文件系統將組織數據時使用的目錄也抽象為文件,以簡化對數據的管理。
★存儲過程假想:
我們模擬對一個分區存儲數據的過程來說明FAT文件系統中數據的存儲原則。
假定現在有一個空的完全沒有存放數據的磁盤,大小為100KB,我們將其想象為線形的空間地址。
為了存儲管理上的便利,我們人為的將這100KB的空間均分成100份,每份1KB。
我們來依次存儲這樣幾個文件:
A.TXT(大小10KB),B.TXT(大小53.6KB),C.TXT(大小20.5KB)。
最起碼能夠想到,我們可以順序的在這100KB空間中存放這3個文件。
同時不要忘了,我們還要記下他們的大小和開始的位置,這樣下次要用時纔能找的到,這就像是目錄。
為了便於查找,我們假定用第1K的空間來存儲他們的特征(屬性)。
還有,我們設計的存儲單位是1KB,所以,A.TXT我們需要10個存儲單位(為了說明方便,我們把存儲單位叫做『簇』吧。
也能少打點字,呵呵。
),B.TXT需要54個簇,C.TXT需要21個簇。
可能有人會說B.TXT和C.TXT不是各自浪費了不到1簇的空間嗎?
乾嘛不讓他們緊挨著,不是省地方嗎?
我的回答是,如果按照這樣的方式存儲,目錄中原本只需要記下簇號,現在還需要記下簇內的偏移,這樣會增加目錄的存儲量,而且存取沒有了規則,讀取也不太方便,是得不償失的。
根據上面所說的思想,我們設計了這樣的圖4.3.1所示的存儲方式。
我們再考慮如何來寫這三個文件的目錄。
對於每個文件而言,一定要記錄的有:
文件名,開始簇,大小,創建日期、時間,修改日期、時間,文件的讀寫屬性等。
這裡大小能不能用結束簇來計算呢?
一定不能,因為文件的大小不一定就是整數個簇的大小,否則的話像B.TXT的內容就是54KB的內容了,少了固然不行,可多了也是不行的。
那麼我們怎麼記錄呢?
可以想象一下。
為了管理上的方便,我們用數據庫的管理方式來管理我們的目錄。
於是我把1KB再分成10份,假定開始簇號為0,定義每份100B的各個位置的代表含義如圖4.3.2
這樣設計的結構絕對可以對文件進行正確的讀寫了。
接著讓我們設計的文件系統工作吧。
先改動個文件,比如A.TXT,增加點內容吧!
咦?
增加後往哪裡放呀,雖然存儲塊的後面有很多空間,但緊隨其後B.TXT的數據還頂著呢?
要是把A.TXT移到後邊太浪費處理資源,而且也不一定解決問題。
這個問題看來暫時解決不了。
那我們換個操作,把B.txt刪了,b.txt的空間隨之釋放。
這時候空間如圖4.3.3,目錄如圖4.3.4
這個操作看來還可以,我們接著做,在存入一個文件D.txt(大小為60.3KB),總共100簇的空間只用了31簇,還有68簇剩餘,按說能放下。
可是?
往那裡放呢?
沒有61個連續的空間了,目錄行沒辦法寫了,看來無連續塊存儲暫時也不行。
你一定能夠想到我們可以在連續空間不夠或增加文件長度的時候轉移影響我們操作的其他文件,從而騰出空間來,但我要問你,那不是成天啥也不要乾了,就是倒騰東西了嗎?
看來我們設計的文件系統有致命的漏洞,怎麼解決呢?
其實可以這樣解決:
首先我們允許文件的不連續存儲。
目錄中依然只記錄開始簇和文件的大小。
那麼我們怎麼記錄文件佔用那些簇呢,以文件映射簇不太方便,因為文件名是不固定的。
我們換個思想,可以用簇來映射文件,在整個存儲空間的前部留下幾簇來記錄數據區中數據與簇號的關系。
對於上例因為總空間也不大,所以用前部的1Kb的空間來記錄這種對應,假設3個文件都存儲,空間分配如圖4.3.5,同時修改一下目錄,如圖4.3.6
第一簇用來記錄數據區中每一簇的被佔用情況,暫時稱其為文件分配表。
結合文件分配表和文件目錄就可以達到完全的文件讀取了。
我們想到,把文件分配表做成一個數據表,以圖4.3.7的形式記錄簇與數據的對應。
用圖4.3.7的組織方式是完全可以實現對文件佔有簇的記錄的。
但還不夠效率。
比如文件名在文件分配表中記錄太多,浪費空間,而實際上在目錄中已經記錄了文件的開始簇了。
所以可以改良一下,用鏈的方式來存放佔有簇的關系,變成圖4.3.8的組織方式。
參照圖4.3.8來理解一下文件分配表的意義。
如文件a.txt我們根據目錄項中指定的a.txt的首簇為2,然後找到文件分配表的第2簇記錄,上面登記的是3,我們就能確定下一簇是3。
找到文件分配表的第3簇記錄,上面登記的是4,我們就能確定下一簇是4......直到指到第11簇,發現下一個指向是FF,就是結束。
文件便絲毫無誤讀取完畢。
我們再看上面提到的第三種情況,就是將b.txt刪除以後,存入一個大小為60.3KB的d.txt。
利用簇鏈可以很容易的實現。
實現後的磁盤如圖4.3.9 4.3.10 4.3.11
上面是我們對文件存儲的一種假設,也該揭開謎底的時候了。
上面的思想其實就是fat文件系統的思想的精髓(但並不是,尤其像具體的參數的意義與我們所舉的例子是完全不同的。
請忘掉上邊細節,努力記憶下邊)。
★FAT16存儲原理:
當把一部分磁盤空間格式化為fat文件系統時,fat文件系統就將這個分區當成整塊可分配的區域進行規劃,以便於數據的存儲。
一般來講,其劃分形式如圖7所示。
我們把FAT16部分提取出來,詳細描述一下