SD卡FAT32文件系统格式
一、聲明
1、本文來源和主旨
2、本文測試環境?
二、SD卡FAT文件系統?
1、SD卡FAT32文件系統的整體布局
2、FAT文件系統簡介
① 文件分配表?
② 目錄項?
三、DBR(DOS BOOT RECORD,DOS引導記錄)
1、DBR與BPB
① DBR
② BPB
2、DBR實例測試
3、DBR參數計算
四、FSINFO分區?
五、文件分區FAT表
1、FAT表
2、FAT表例?
六、數據區
1、目錄項定義?
<1> 短文件目錄項的具體定義
<2> 長文件目錄項的具體定義?
2、目錄項舉例
<1> 短目錄項舉例
<2>? 長目錄項舉例
?
一、聲明
1、本文來源和主旨
本文幾乎全部內容來自于SD卡中FAT32文件格式快速入門(圖文詳細介紹),這篇文章的理論闡釋很到位,實驗編排也不錯。本文所做的工作就是將這篇文章中講解的實驗從頭到尾做一遍。另外本文對于原文的編排有所調整,希望達到更加合理的布局。
2、本文測試環境
測試硬件:2G金士頓SD卡(格式化)
操作系統:"Windows XP"
測試軟件:WinHex
二、SD卡FAT文件系統
1、SD卡FAT32文件系統的整體布局
本SD卡的FAT32文件系統無MBR分區,只有一個基本分區,而基本分區的分布圖如下圖所示:
從WinHex中查看
2、FAT文件系統簡介
FAT(File?Allocation?Table,文件分配表)文件系統是windows操作系統所使用的一種文件系統,它的發展過程經歷了FAT12、FAT16、FAT32三個階段。FAT文件系統用“簇”作為數據單元。一個“簇”由一組連續的扇區組成,簇所含的扇區數必須是2的整數次冪。簇的最大值為64個扇區,即32KB。所有簇從2開始進行編號,每個簇都有一個自己的地址編號。用戶文件和目錄都存儲在簇中。?本文每簇4KB大小。
FAT文件系統的數據結構中有兩個重要的結構:文件分配表和目錄項:
① 文件分配表
文件和文件夾內容儲存在簇中,如果一個文件或文件夾需要多余一個簇的空間,則用FAT表來描述,如何找到另外的簇。FAT結構用于指出文件的下一個簇,同時也說明了簇的分配狀態。FAT12、FAT16、FAT32這三種文件系統之間的主要區別在與FAT項的大小不同。?
② 目錄項
FAT文件系統的每一個文件和文件夾都被分配到一個目錄項,目錄項中記錄著文件名、大小、文件內容起始地址以及其他一些元數據。?
在FAT文件系統中,文件系統的數據記錄在“引導扇區中(DBR)”中。引導扇區位于整個文件系統的0號扇區,是文件系統隱藏區域(也稱為保留區)的一部分,我們稱其為DBR(DOS?Boot?Recorder——DOS引導記錄)扇區,DBR中記錄著文件系統的起始位置、大小、FAT表個數及大小等相關信息。
在FAT文件系統中,同時使用“扇區地址”和“簇地址”兩種地址管理方式。這是因為只有存儲用戶數據的數據區使用簇進行管理(FAT12和FAT16的根目錄除外),所有簇都位于數據區。其他文件系統管理數據區域是不以簇進行管理的,這部分區域使用扇區地址進行管理。文件系統的起始扇區為0號扇區。
三、DBR(DOS BOOT RECORD,DOS引導記錄)
1、DBR與BPB
① DBR
DBR(DOS?Boot?Recorder——DOS引導記錄)扇區,DBR中記錄著文件系統的起始位置、大小、FAT表個數及大小等相關信息。
?
② BPB
BPB(BIOS Parameter Block)表,描述邏輯盤結構組成,包含隱藏扇區數目(從0-1-1開始計算)、FAT扇區數、FAT拷貝數、硬盤磁頭總數、根目錄表項最大值等。
FAT32文件系統的擴展BPB區位于DBR內,從地址0x00B~0x052都是BPB的范圍。
2、DBR實例測試
格式化SD卡,用WinHex打開SD卡,內容如下:
【1】0x00~0x02:3字節,"EB5890",跳轉指令。?
【2】0x03~0x0A:8字節,文件系統標志和版本號,這里為MSDOS5.0。?
【3】0x0B~0x0C:2字節,每扇區字節數,512(0X02 00)。?
【4】0x0D~0x0D:1字節,每簇扇區數,8(0x08),這個值不能為0,而且必須是2的整數次方,比如1、2、4、8、16、32、64、128。
【5】0x0E~0x0F:2字節,保留扇區數,38(0x00?26),那么就知道FAT1起始位置在38扇區。??
【6】0x10~0x10:1字節,FAT表個數為2,另外一個是備份的。?
【7】0x11~0x12:2字節,FAT32必須等于0,FAT12/FAT16為根目錄中目錄的個數;?
【8】0x13~0x14:2字節,FAT32必須等于0,FAT12/FAT16為扇區總數。?
【9】0x15~0x15:1字節,哪種存儲介質,0xF8標準值,可移動存儲介質。?
【10】0x16~0x17:2字節,FAT32必須為0,FAT12/FAT16為一個FAT表所占的扇區數。
【11】0x18~0x19:2字節,每磁道扇區數,只對于有“特殊形狀”(由磁頭和柱面每 分割為若干磁道)的存儲介質有效,63(0x003F)。?
【12】0x1A~0x1B:2字節,磁頭數,只對特殊的介質才有效,255(0x00 FF)。?
【13】0x1C~0x1F:4字節,EBR分區之前所隱藏的扇區數,0(0x00?00 00?00)。
【14】0x20~0x23:4字節,此文件系統分區的總扇區數,3887104(0x?00 3B?50 00),3887104?* 512?= 1990197248??≈?1.9GB。
【15】0x24~0x27:4字節,每個FAT表占用扇區數,3789(0x?00?00 0E?CD)。?
【16】0x28~0x29:2字節,標記,此域FAT32?特有。?
【17】0x2A~0x2B:2字節,FAT32版本號0.0,FAT32特有。?
【18】0x2C~0x2F:4字節,根目錄所在第一個簇的簇號,2。(雖然在FAT32文件系統?下,根目錄可以存放在數據區的任何位置,但是通常情況下還是起始于2號簇)。
【19】0x30~0x31:2字節,FSINFO(文件系統信息扇區)扇區號是1,該扇區為操作系統提供關于空簇總數及下一可用簇的信息。?
【20】0x32~0x33:2字節,備份引導扇區的位置。備份引導扇區總是位于文件系統的6號扇區。?
【21】0x34~0x3F:12字節,用于以后FAT?擴展使用。??
【22】0x40~0x40:1字節,與FAT12/16?的定義相同,只不過兩者位于啟動扇區不同的位置而已。
【23】0x41~0x41:1字節,與FAT12/16?的定義相同,只不過兩者位于啟動扇區不同的位置而已?。?
【24】0x42~0x42:1字節,擴展引導標志,0x29。與FAT12/16?的定義相同,只不過兩者位于啟動扇區不同的位置而已
【25】0x43~0x46:4字節,卷序列號。通常為一個隨機值。?
【26】0x47~0x51:11字節,卷標(ASCII碼),如果建立文件系統的時候指定了卷標,會保存在此。?
【27】0x52~0x59:8字節,文件系統格式的ASCII碼,FAT32。?
★【28】0x5A~0x1FD:90~509共410字節,引導代碼。?
【29】0x1FE~0x1FF:簽名標志“55?AA”。?
★說明:引導代碼
FAT文件系統將引導代碼與文件形同數據結構融合在一起,FAT32文件系統引導扇區的512字節中,90~509字節為引導代碼,而FAT12/16則是62~509字節為引導代碼。同時,FAT32還可以利用引導扇區后的扇區空間存放附加的引導代碼。一個FAT卷即使不是可引導文件文件系統,也會存在引導代碼。
3、DBR參數計算
由以上信息我們知道:
扇區大小:512 Bytes
簇大小:8 Sector = 2048 Bytes
保留扇區數:38 Sector
FAT表占用扇區數:3789 Sector
所以可以得知:
(1)FAT1地址
= 38 * 512 = 19456 = 0x4C00
(2) FAT2地址
= (38 + 3789)*512 = 1959424 = 0x1DE600
(3) 根目錄地址
= (38 + 3789 * 2)* 512 = 3899392 = 0x3B8000
(4) FAT表占據扇區數
= 簇總數 * 4 Bytes/ 扇區占據字節數
= (數據區扇區數/每簇占據扇區數)* 4 / 512
= ( 3879488 / 8 ) * 4 / 512
= 3788.5625
FAT表占據扇區數取整數為3789Sector。
四、FSINFO分區
FAT32在保留區中增加了一個FSINFO扇區,用以記錄文件系統中空閑簇的數量以及下一可用簇的簇號等信息,以供操作系統作為參考。FSINFO信息扇區一般位于文件系統的1號扇區,結構非常簡單。
【1】0x200~0x203:?4個字節,擴展引導標志“0x52526141”。?
【2】0x204~0x3E3:480個字節,未使用,全部置0。?
【3】0x3E4~0x3E7:?4個字節,FSINFO簽名“0x72724161”。?
【4】0x3E8~0x3EB:?4個字節,文件系統的空簇數,484934(0x00 07 66 46)。?
【5】0x3EC~0x3EF:?4個字節,下一可用簇號(0x?00?00?00 04)。?
【6】0x3F0~0x3FD:?14個字節,未使用。?
【7】0x3FE~0x3FF:?2個字節,“55?AA”標志。??
溫馨提示:通常情況下,文件系統的2號扇區結尾也會被設置“55?AA”標志。6號扇區會有一個引導扇區的備份,7號扇區是一個FSINFO信息備份扇區,8號扇區可以看做是2號扇區的備份。
?五、文件分區FAT表
文件系統分配磁盤空間按簇來分配。因此,文件占有磁盤空間時,基本單位不是字節而是簇,即使某個文件只有一個字節,操作系統也會給它分配一個最小單元:即一個簇。對于大文件,需要分配多個簇。同一個文件的數據并不一定完整地存放在磁盤中一個連續地區域內,而往往會分若干段,像鏈子一樣存放。這種存儲方式稱為文件的鏈式存儲。為了實現文件的鏈式存儲,文件系統必須準確地記錄哪些簇已經被文件占用,還必須為每個已經占用的簇指明存儲后繼的下一個簇的簇號,對于文件的最后一簇,則要指明本簇無后繼簇。這些都是由FAT表來保存的,FAT?表對應表項中記錄著它所代表的簇的有關信息:諸如是空,是不是壞簇,是否是已經是某個文件的尾簇等。
1、FAT表?
FAT表中的表項也是以4字節為單位進行劃分,對FAT表由0進行邏輯編號。0號地址與1號地址被系統保留并存儲特殊標志內容。從2號地址開始,每個地址對應于數據區的簇號,FAT表中的地址編號與數據區中的簇號一一對應。我們稱FAT表中的這些單元為FAT表項,FAT表項中記錄的值稱為FAT表項值。?
FAT32中把簇是以32bit(4個字節)進行編碼,而這種編碼是邏輯編碼,與物理地址也有一定的對應關系。FAT表緊接著的是有效數據區,從此區開始從2進行簇標號。也就是說從物理地址0x3B8000(7616扇區)位置處,從2開始,以4KB (8*512)為跨度進行簇編號。
? ? 當文件系統被創建,也就是進行格式化操作時,分配給FAT區域的空間將會被清空,在FAT1與FAT2的0號表項與1號表項寫入特定值。由于創建文件系統的同時也會創建根目錄,也就是為根目錄分配了一個簇空間,通常為2號簇,與之對應的2號FAT表項被寫入一個結束標記。
說明:
① 由于簇號起始于2號,所以FAT表項的0號表項與1號表項不與任何簇對應。FAT32的0號表項值總是“F8FFFF0F”。
② ?1號表項可能被用于記錄臟標志,以說明文件系統沒有被正常卸載或者磁盤表面存在錯誤。不過這個值并不重要。正常情況下1號表項的值為“FFFFFFFF”或“FFFFFF0F”。
② ?如果某個簇未被分配使用,它對應的FAT表項內容為0;
③ 當某個簇已被分配使用,則它對應的FAT表項內的FAT表項值也就是該文件的下一個存儲位置的簇號。如果該文件結束于該簇,則在它的FAT表項中記錄的是一個文件結束標記,對于FAT32而言,代表文件結束的FAT表項值為0x0FFFFFFF。
③ 如果某個簇存在壞扇區,則整個簇會用0xFFFFFF7標記為壞簇,這個壞簇標記就記錄在它所對應的FAT表項中。
④ ?在文件系統中新建文件時,如果新建的文件只占用一個簇,為其分配的簇對應的FAT表項將會寫入結束標記。如果新建的文件不只占用一個簇,則在其所占用的每個簇對應的FAT表項中寫入為其分配的下一簇的簇號,在最后一個簇對應的FAT表象中寫入結束標記。
⑤ 新建目錄時,只為其分配一個簇的空間,對應的FAT表項中寫入結束標記。當目錄增大超出一個簇的大小時,將會在空閑空間中繼續為其分配一個簇,并在FAT表中為其建立FAT表鏈以描述它所占用的簇情況。
2、FAT表例
筆者先對2G金士頓SD卡進行格式化,然后新建一個readme.txt文件,大小8.9KB。
用WinHex打開FAT1區,內容如下
【0號表項】:0x0FFFFFF8;FAT表起始固定標識
【1號表項】:0xFFFFFFFF;不用,默認值
【2號表項】:0x0FFFFFFF;根目錄所在簇,由于此時只占用1簇,所以是結束標志
【3號表項】:3號表項為0x00?00?00?04,readme.txt文件的下一簇號在4號表項,查看4號表項。
【4號表項】:4號表項為0x00?00?00?05,readme.txt文件下一簇號在5號表項,查看5號表項。
【5號表項】:5號表項為0x0F?FF?FF?FF,結束符號。說明文件在5號簇時就存儲完畢。
分析:readme.txt大小為8.9KB,而每簇大小為4KB,需要占用3個簇,這與存儲結果一致。
?六、數據區
數據區時真正用于存放用戶數據的區域。數據區緊跟在FAT2之后,被劃分成一個個的簇。所有的簇從2開始進行編號,也就是說,2號簇的起始位置就是數據區的起始位置。
1、目錄項定義
目錄所在的扇區,都是以32?Bytes劃分為一個單位,每個單位稱為一個目錄項(Directory?Entry),即每個目錄項的長度都是32?Bytes?。根目錄由若干個目錄項組成,一個目錄項占用32個字節,可以是長文件名目錄項、文件目錄項、子目錄項等。
<1> 短文件目錄項的具體定義
☆ 目錄項的第一個字節為“0xE5”,表示該項已被刪除。
☆?目錄項的第一個字節為0x2E(“.”),表示當前目錄的信息(目錄的數據空間也會保存當前目錄的目錄項信息)
☆?目錄項的前兩個字節為“0x2E?0x2E(“.?.”),表示上一級目錄。
☆ 目錄項的第一個字節為"0x00",代表從此位置開始以后的數據空間都沒有使用。
注意:
對于目錄對應的短目錄項,沒有文件長度參數,也就是說0x1C-0x1F等于0。那么對于目錄,又如何知道它占用空間的大小呢,又如何遍歷目錄呢?
目錄中的目錄項是按照從前到后緊密排放,即使文件或者目錄刪除,也不會刪除它們對應的目錄項(刪除目錄項意味著目錄項清零),只是將目錄項標記為刪除(0xE5)。這樣目錄的數據空間直到遇到第一個空目錄項之前,所有的目錄項都是非空的。我們可以根據目錄項是否非空判斷是否到達了目錄的目錄項尾部。
至于目錄的大小,其實已經沒有意義了。我們獲取目錄的大小就是想判斷目錄的結束位置,而現在第一個空目錄項就是目錄的結束位置,所以已經沒有必要知道目錄的大小。當然, 通過遍歷目錄可以確定目錄占用空間的大小,不過沒有意義。
<2> 長文件目錄項的具體定義
再詳細的列出上表中地址0x0處各位段的含義
☆ 長文件名文件目錄項的unicode編碼:無論是英文字符,還是中文字符都占用2個字節。
☆ 目錄項的第一個字節為“0xE5”,表示該項已被刪除。
☆ ?一個長文件它在目錄中的記錄可能有幾個目錄項組成,包含若干個長目錄項和一個短目錄項
☆ 0xB位段的取值如果是0FH代表是長目錄項,反之就是短目錄項。
☆ 1個長文件目錄項:能記錄13個字符,對應26個字節
☆ 順序是從1開始編號直到13,倘若到了結尾的地方,除了要按照規則的編號還需要將0x0地址的第6位置1。
2、目錄項舉例
<1> 短目錄項舉例
格式化SD卡,然后在其中創建一個文件readme.txt和Test子目錄,WinHex打開根目錄內容如下:
首先看子目錄Test的對應目錄項:
【1】0x3B8020 -?0x3B8027 目錄項名為Test
【2】0x3B802B 10H(0001 0000B),表明為子目錄
【3】[0x3B8034 -?0x3B8035,0x3B803A -?0x3B803B] ?00 03H,表明Test子目錄位于3號簇的位置,在FAT表中為3號表項
【4】0x3B803C -?0x3B803F 0000H,大小為0
readme.txt的對應目錄項:
【1】0x3B8040 -?0x3B8047 目錄項名為readme
【2】0x3B8048 - 0x3B804A 目錄項擴展名為TXT
【3】0x3B804B 20H(0010 0000B),表明為歸檔文件
【3】[0x3B8054 -?0x3B8055,0x3B805A -?0x3B805B] ?00 04H,表明readme.txt位于4號簇的位置,在FAT表中為4號表項
【4】0x3B805C -?0x3B805F 23A7H,大小為9127 Bytes
<2>? 長目錄項舉例
格式化SD卡,然后在其中創建一個文件abcdefghigklmnopqrstuvwxyz.txt,WinHex打開根目錄內容如下:
先看看卷標?
【1】0x3B8000 -?0x3B8007 目錄項名為Huang?
【2】0x3B800B 08H(0000 1000B),表明為"卷標"
再看看長文件目錄項
【1】003B8020 0x43 表明此長文件包含了3個長目錄項,并且當前目錄項是它的最后一個長目錄項
【2】003B8040 0x02 表明這是長文件的第2個目錄項
【3】003B8041 - 003B804A?長文件目錄項的unicode的第一部分, 006EH 006FH 0070H 0071H 0072H 代表了nopqr五個字符
【4】003B804B 0x0F 表明是一個長目錄項
【5】003B804D???? 0x27 校驗和
【6】003B804E -003B8059 長文件目錄項的unicode的第二部分, 0073H 0074H 0075H 0076H 0077H 0078H?代表了stuvwx六個字符
【7】003B805A - 003B805B 起始簇號,目前常置0
【8】003B805C - 003B805F 長文件目錄項的unicode的第三部分,?0079H 007AH?代表了yz兩個字符
為了記錄abcdefghigklmnopqrstuvwxyz.txt,使用了3個長目錄項和1個短目錄項。至于位于003B8080處的短目錄項,就不在說明了。
?
參考資料:SD卡中FAT32文件格式快速入門(圖文詳細介紹)
FAT文件系統原理(一)
? ? ? ? ? ? ? FAT(維基百科)
?
轉載于:https://www.cnblogs.com/amanlikethis/p/3775902.html
總結
以上是生活随笔為你收集整理的SD卡FAT32文件系统格式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: g_thread_init
- 下一篇: Seay工具分享