1.簡介
在早期計算機剛發(fā)展的時候,那時候硬盤大小、flash設(shè)備容量都比較小,隨著技術(shù)的不斷迭代更新,硬盤容量越來越大。在早期,面對小容量的硬盤/flash,往往采用對應(yīng)地址存放對應(yīng)數(shù)據(jù)的方案,由于數(shù)據(jù)量不大,操作起來尚還可以。但是發(fā)展到今天,隨著硬盤/flash容量不斷增大,存儲的數(shù)據(jù)也越來越多,早期單一的對應(yīng)地址存放對應(yīng)數(shù)據(jù)的方案已經(jīng)無法滿足我們的需求,操作硬盤/flash會變得異常的困難復雜。
因此針對上述問題,一群大佬們便開始設(shè)計文件系統(tǒng)這樣一個東西,用來管理硬盤/flash上的數(shù)據(jù)信息,像我們電腦上打開文件夾,訪問里面的文件,這其實就是基于文件系統(tǒng)訪問電腦硬盤上數(shù)據(jù)的一個操作。
發(fā)展至今,文件系統(tǒng)已有眾多版本,本文主要分享 關(guān)于FAT文件系統(tǒng)的詳細設(shè)計, FAT文件系統(tǒng)適用于嵌入式設(shè)備,如SD卡、SD nand、spi nor flash等眾多存儲設(shè)備,同時基于此文件系統(tǒng)的文件亦能被電腦正常讀取。
2.基礎(chǔ)概念
在研究文件系統(tǒng)之前,我們需要首先弄清楚關(guān)于內(nèi)存這塊的幾個基本概念:
區(qū)分 ==扇區(qū)、塊、簇== 的概念
扇區(qū)(sector):flash可操作的最小單元,通常指我們擦除的最小單元大小,以sd nand舉例,通常最小為512Byte
塊(block) 以及 簇(cluster):其實這是兩個相同的概念,只是由于歷史原因,在不同系統(tǒng)上的不同稱呼,在windows中稱簇,而在linux中稱塊。一個簇/塊由多個扇區(qū)組成,由于一個扇區(qū)的空間較小,因此文件系統(tǒng)通過會將多個扇區(qū)組合在一起形成一個簇,并以簇為單位進行讀寫操作! 一個簇通常可以由 2、4、8、… 、2的n次方個扇區(qū)組成。
FAT文件系統(tǒng)總共由FAT12、FAT16以及FAT32三個版本,這是由于隨著存儲技術(shù)不斷發(fā)展,F(xiàn)AT文件系統(tǒng)迭代導致,數(shù)字越大,版本越新,新版本對老版本完全兼容!
3.FAT文件系統(tǒng)組成介紹
FAT文件系統(tǒng)在flash上的布局如下圖所示,總共由四個區(qū)域組成:
保留區(qū)
FAT區(qū)
根目錄區(qū) (FAT32類型不包含此區(qū)域)
數(shù)據(jù)區(qū)
接下來,我們對一張格式化為FAT格式的SD卡進行分析,理解FAT文件系統(tǒng)的實現(xiàn)細節(jié):
4.FAT文件系統(tǒng)分析
4.1 采用FAT格式格式化SD nand/sd卡
使用win10格式化一張118.5M的SD nand / sd卡,我這里用的是手上的一顆 創(chuàng)世CS 家的sd nand加一塊轉(zhuǎn)接板,和SD卡完全沒有區(qū)別,且SD nand在穩(wěn)定性上比SD卡具有優(yōu)勢。
==此處由于SD nand(SD卡)大小原因,默認采用FAT16進行了格式化!因此在下文中我們先以FAT16進行分析,之后再重新格式化為FAT32進行分析,就很容易懂了!==
4.2 引導扇區(qū)分析
使用 winhex 工具打開對應(yīng)磁盤,注意需使用管理員權(quán)限運行
==此處由于SD nand(SD卡)大小原因,默認采用FAT16進行了格式化!因此在下文中我們先以FAT16進行分析,之后再重新格式化為FAT32進行分析,就很容易懂了!==
4.2 引導扇區(qū)分析
使用 winhex 工具打開對應(yīng)磁盤,注意需使用管理員權(quán)限運行
a) 首先是FAT12/16/32公共部分,(偏移值 0 - 35):
EB 3C 90:BS_JmpBoot,跳轉(zhuǎn)指令
4D 53 44 4F 53 35 2E 30:BS_OEMName,MSDOS 5.0,一個名字,指示創(chuàng)建此卷的操作系統(tǒng),無其他作用
00 02:BPB_BytsPerSec,扇區(qū)大小 512 字節(jié)
04:BPB_SecPerClus,每次操作的最小扇區(qū)數(shù),簇 Cluster,4 (與格式化時選擇的大小匹配 2048 = 512 * 4)
06 00:BPB_RsvdSecCnt,保留區(qū)的扇區(qū)數(shù),6 (通過此可計算,F(xiàn)AT區(qū)起始地址為 6 * 512 = 0xC00)
02:BPB_NumFATs,F(xiàn)ATs的個數(shù),2(一般此值為2,多一個用來做冗余備份,解決系統(tǒng)異常導致第一個損壞時,增大恢復的可能性,表示FAT區(qū)有兩個FATs備份)
00 02:BPB_RootEntCnt,512,在FAT12/16系統(tǒng)中,此字段表示根目錄中32字節(jié)目錄條目數(shù)量,設(shè)置此值時需注意對齊,為了最大的兼容性,F(xiàn)AT16系統(tǒng)上此值應(yīng)設(shè)置為512,F(xiàn)AT32系統(tǒng)上此值應(yīng)設(shè)置為0
00 00:BPB_TotSec16,16位大小區(qū)域描述FAT卷扇區(qū)總數(shù),0。當FAT12/16系統(tǒng)扇區(qū)數(shù) ≥0x10000(65536)時,此字段應(yīng)設(shè)置為0,真實值存放在 BPB_TotSec32 字段;對于FAT32系統(tǒng),此值必須為0。(此處由于我們的總扇區(qū)數(shù)=118.510241024/512 = 242688 > 65536,所以此字段為0)
F8:BPB_Media 媒體類型
ED 00:BPB_FATSz16,237,一個FAT占用的扇區(qū)數(shù),此字段僅在FAT12/16系統(tǒng)使用;FAT32系統(tǒng),此字段必須為0,使用BPB_FATSz32字段替代。FAT區(qū)總大小等于 BPB_FATSz?? BPB_NumFATs 扇區(qū)(2372*512=242688=0x3B400,由此可推算根目錄區(qū)起始地址:0x3B400+0xC00=0x3C000)。
3F 00:BPB_SecPerTrk,每個磁道的扇區(qū)數(shù),此字段僅與具有幾何形狀且僅用于 IBM PC 的磁盤 BIOS 的介質(zhì)相關(guān),不用管。
FF 00:BPB_NumHeads,頭數(shù)量,此字段僅與具有幾何形狀且僅用于 IBM PC 的磁盤 BIOS 的介質(zhì)相關(guān),不用管。
00 00 00 00:BPB_HiddSec,0,F(xiàn)AT 卷之前的隱藏物理扇區(qū)數(shù)(當磁盤被分區(qū)之后,當前分區(qū)并不一定是從扇區(qū)頭開始的)
00 B4 03 00:BPB_TotSec32,242688,32位大小區(qū)域描述FAT卷扇區(qū)總數(shù)(整個卷空間大?。?。 FAT12/16系統(tǒng),扇區(qū)總數(shù)小于0x10000時,此字段必須為0,真實值存放在BPB_FATSz16;FAT32系統(tǒng),此字段一直有效。(118.5M = 512 * 242688)
b) 接下來是FAT12/16特有字段(偏移值36)
80:BS_DrvNum,IBM PC 的磁盤 BIOS 使用的驅(qū)動器號,00h代表軟盤,80h代表固定磁盤
00:BS_Reserved,保留字段,0
29:BS_BootSig,擴展引導簽名,表示以下存在三個字段
83 3E 07 E4:BS_VolID,與 BS_VolLab 一起構(gòu)成卷序列號,一般在格式化的時候結(jié)合時間生成
4E 4F 20 4E 41 4D 45 20 20 20 20:(解析為:”NO NAME “),BS_VolLab,11byte卷標,當卷標不存在時,此值應(yīng)設(shè)置為”NO NAME”
46 41 54 31 36 20 20 20:(解析為:”FAT16 “),BS_FilSysType文件系統(tǒng)類型,支持字段有:”FAT12 “, “FAT16 “ or “FAT “,注意很多人認為是通過此字段區(qū)分FAT12/16/32系統(tǒng)類型,實際是錯誤的,文件系統(tǒng)類型實際上是根據(jù)磁盤大小確定的,官方文檔 “Determination of FAT sub-type” 章節(jié)或本博文后文有描述,不過為了最大的兼容性考慮,此字段應(yīng)設(shè)置為對應(yīng)文件系統(tǒng)的名字。
33 C9 ~ CB D8:BS_BootCode,引導啟動程序,與平臺有關(guān),不使用時填充為0
55 AA:BS_BootSign,0xAA55,引導簽名,指示這是一個有效的引導扇區(qū)
當扇區(qū)大小大于512字節(jié)時,剩余的字段應(yīng)全部使用0x0填充。
c) 如果是FAT32,則采用FAT32特有字段解析(偏移值和FAT12/16特有字段一致為36)
雖然此處我們的是FAT16格式,不過此處也將FAT的字段進行描述,方便理解。
BPB_FATSz32:一個FAT占用的扇區(qū)數(shù),此字段僅在FAT32系統(tǒng)有效。FAT區(qū)總大小等于 BPB_FATSz?? * BPB_NumFATs 扇區(qū)。
BPB_ExtFlags:擴展標識字段,bit7=0,表示所有FAT都是鏡像的和活躍的;bit7=1,表示只有bit3-0表示的FAT是有效的。
BPB_FSVer:FAT32版本,高字節(jié)是主版本號,低字節(jié)是次版本號。
BPB_RootClus:根目錄的第一個簇號,此值通常為2,因為前兩個簇一般用于保留。
BPB_FSInfo:FSInfo結(jié)構(gòu)扇區(qū)與FAT32卷頂部的偏移扇區(qū)值。此值通常為1,因為其通常位于引導扇區(qū)旁邊。
BPB_BkBootSec:備份引導扇區(qū)與FAT32卷頂部的偏移扇區(qū)值。此值通常為6,考慮最大的兼容性,此值不建議為其他值。
BPB_Reserved:保留
BS_DrvNum:含義與FAT12/16字段一樣
BS_Reserved:含義與FAT12/16字段一樣
BS_BootSig:含義與FAT12/16字段一樣
BS_VolID:含義與FAT12/16字段一樣
BS_VolLab:含義與FAT12/16字段一樣
BS_FilSysType:始終為”FAT32 “,對FAT類型的確定沒有任何影響。
BS_BootCode32:引導啟動程序,與平臺有關(guān),不使用時填充為0
BS_BootSign:0xAA55,引導簽名,指示這是一個有效的引導扇區(qū)
當扇區(qū)大小大于512字節(jié)時,剩余的字段應(yīng)全部使用0x0填充。
以上就是引導扇區(qū)內(nèi)容的詳細分析了,通過引導扇區(qū)的內(nèi)容,我們即可知道FAT文件系統(tǒng)依賴的硬件存儲空間大小、簇大小、扇區(qū)大小以及以及FAT系統(tǒng)版本等重要信息。
同時通過引導扇區(qū)的內(nèi)容,我們便可計算出對應(yīng)的FAT的四個區(qū)域的大小及起始偏移位置等重要信息,接下來計算FAT四個分區(qū)的起始位置及大小。
4.3 分區(qū)偏移及大小計算
FAT卷總共分為以下四個區(qū)域:
保留區(qū)
第一個扇區(qū)為引導扇區(qū),存放BPB(BIOS Parameter Block)數(shù)據(jù),存放的是FAT卷的配置參數(shù)。
上述參數(shù)中以 BPB 命名的字段都是 BPB 的一部分,而以 BS 標題命名的字段都不是 BPB 的一部分,而只是引導扇區(qū)的一部分
FAT區(qū)(分區(qū)表裝載區(qū))
根目錄區(qū)
數(shù)據(jù)區(qū)
各分區(qū)偏移地址及大小如下:
此外,關(guān)于FAT區(qū),通常存在一個以上的FAT,如此處所格式化的sd卡便存在兩個FAT,對應(yīng)的偏移地址和大小如下:
4.4 FAT子類型確認
關(guān)于FAT的類型是FAT12/16/32確認:FAT類型由數(shù)據(jù)區(qū)內(nèi)簇的數(shù)量決定,除此之外無其他辦法!
當一個卷,簇的數(shù)量 ≤4085 時,為FAT12
當一個卷,簇的數(shù)量 ≥4086 且 ≤65525 時,為FAT16
當一個卷,簇的數(shù)量 ≥65526 時,為FAT32
簇的數(shù)量計算公式:CountofClusters = DataSectors / BPB_SecPerClus;
如我們這里:CountofClusters = ==242176== / 4 = 60544,==所以為 FAT16!==
當簇的大小從 512 ~ 32768字節(jié)的各種條件下,不同類型FAT對應(yīng)卷的大小范圍如下:
4.4 訪問FAT條目
FAT區(qū)由一條條FAT條目構(gòu)成,關(guān)于 FAT[N] 對應(yīng)的條目具體位置計算如下:
格外需要注意的是,不同格式,對應(yīng)的FAT條目的長度和格式不一樣:
此外對于FAT32格式,高4位是保留位,只有低28位有效!
具體如下圖所示:
4.5 文件與簇之間的關(guān)系
那么文件和簇之間的相互關(guān)系又是怎樣的呢?我們又是如何準確的找到存放在flash上的文件的呢?接下來讓我們看下文件與簇之間的關(guān)系映射。
在FAT卷上文件通過目錄管理,==目錄是一個32字節(jié)數(shù)組組成的目錄條目結(jié)構(gòu)==,此目錄結(jié)構(gòu)包含:文件名、文件大小、時間戳以及文件所在的第一個簇號。
簇號為0和1的簇被保留,由參數(shù)BPB_RootClus可知,有效簇從第2號簇開始。==FAT2對應(yīng)數(shù)據(jù)區(qū)的第一個簇==。
因此第N個簇的位置計算公式如下:
FirstSectorofCluster = DataStartSector + (N - 2) * BPB_SecPerClus
==每個條目所在的位置,對應(yīng)一個簇。當文件長度大于一個簇長度時,條目內(nèi)的值為下一個條目的索引,直到文件所在的最后一個簇,由此構(gòu)成簇鏈!文件所在的最有一個簇所對應(yīng)的FAT條目內(nèi)的值由一個特殊的值(EOC)組成,它永遠不會匹配任何有效的簇號==,如下:
FAT12: 0xFF8 - 0xFFF (typically 0xFFF)
FAT16: 0xFFF8 - 0xFFFF (typically 0xFFFF)
FAT32: 0x0FFFFFF8 - 0x0FFFFFFF (typically 0x0FFFFFFF)
存在一些特殊的值被用來做損壞簇的標記,如下:
FAT12: 0xFF7
FAT16:0xFFF7
FAT32:0xFFFFFFF7
不過此處需要注意,在FAT12/16系統(tǒng)上,上述特殊值絕不會和任何有效簇匹配,但是在FAT32上有可能,因此為了防止混淆,你在創(chuàng)建FAT32系統(tǒng)的時候應(yīng)該避免這種情況發(fā)生!因此FAT32系統(tǒng)上簇的上限為268435445(大于256M個簇)
FAT條目初始化的時候,F(xiàn)AT[2] 及以后的數(shù)據(jù)應(yīng)被初始化為0,指示未被使用處于空閑狀態(tài),如果值不為0,則意味著簇被損壞或被使用狀態(tài)。在FAT12/16系統(tǒng)上,空閑簇的數(shù)量未被記錄,而在FAT32系統(tǒng)上,F(xiàn)AT32支持FSInfo結(jié)構(gòu)體,里面記錄了空閑簇的數(shù)量。
==關(guān)于FAT[0]和FAT[1]:==
此兩個保留的條目,沒有與任何簇有聯(lián)系;不過具有其他意義,如下:
FAT12: FAT[0] = 0xF??; FAT[1] = 0xFFF;
FAT16: FAT[0] = 0xFF??; FAT[1] = 0xFFFF;
FAT32: FAT[0] = 0xFFFFFF??; FAT[1] = 0xFFFFFFFF;
FAT[0]中的?? 與 BPB_Media 相同;
FAT[1] 記錄了錯誤歷史記錄:卷臟標志(FAT16:bit15、FAT32:bit31),系統(tǒng)在啟動的時候清除此位,正常關(guān)閉的時候恢復。
如果此位已經(jīng)清除,表明上次未被正常關(guān)閉,可能存在邏輯卷錯誤;硬件錯誤標志(FAT16:bit14、FAT32:bit30)當出現(xiàn)無法恢復的讀寫錯誤時清除,表明需要進行全面檢查。
==關(guān)于FAT區(qū)域,有兩個重點注意事項:==
第一個是FAT的最后一個扇區(qū)可能沒有被完全使用。在大多數(shù)情況下,F(xiàn)AT在扇區(qū)的中間結(jié)束。FAT驅(qū)動程序不應(yīng)該對未使用的區(qū)域做出任何假設(shè)。在格式化卷時,應(yīng)該用零填充它,并且在此之后不應(yīng)更改它。
另一個是BPB_FATSz16/32可以指示比卷需要的值大的值。換句話說,未使用的扇區(qū)可以跟隨每個FAT。這可能是數(shù)據(jù)區(qū)域?qū)R或其他原因?qū)е碌摹M瑫r,在格式化時這些扇區(qū)也會被用零填充。
下表展示了不同F(xiàn)AT類型中FAT值所對應(yīng)的含義解釋:
4.6 FSInfo扇區(qū)結(jié)構(gòu)及備份引導扇區(qū)
此部分內(nèi)容只在FAT32系統(tǒng)上存在,對于FAT12系統(tǒng)FAT區(qū)域大小最大6KB,對于FAT16系統(tǒng)FAT區(qū)域最大128KB,但是在FAT32系統(tǒng)上FAT區(qū)域通常上達數(shù)MB,這是因為FAT32系統(tǒng)支持FSInfo數(shù)據(jù)結(jié)構(gòu)。
在FAT32系統(tǒng)上新增FSInfo數(shù)據(jù)結(jié)構(gòu)的原因是:在FAT12/16系統(tǒng)上,想要知道flash上剩余的簇數(shù)需要掃描整個FAT區(qū)才能計算出來,但隨著flash容量的不斷擴大,掃描花費的時長越來越長,為了避免掃描浪費過多的時間,因此在FAT32系統(tǒng)上增加了FSInfo結(jié)構(gòu),用于記錄flash上剩余的簇數(shù)。
FSInfo數(shù)據(jù)結(jié)構(gòu)如下:
| 字段名 | 偏移 | 大小 | 描述 |
| — | — | — | — |
| FSI_LeadSig | 0 | 4 | 固定值為0x41615252,頭部簽名 |
| FSI_Reserved1 | 4 | 480 | 保留區(qū)域,采用0x00覆蓋 |
| FSI_StrucSig | 484 | 4 | 固定值為0x61417272,也是一個簽名 |
| FSI_Free_Count | 488 | 4 | 記錄了空閑的簇數(shù),如果這個值為0xFFFF FFFF,則表示不知道具體的空閑簇數(shù) |
| FSI_Nxt_Free | 492 | 4 | 提示驅(qū)動程序應(yīng)該從此參數(shù)提示的簇開始尋找空閑的簇,通過此參數(shù)便可以不用從FAT區(qū)頭開始尋找下一個空閑簇了,節(jié)省了大量時間;如果此參數(shù)為0xFFFF FFFF,則驅(qū)動程序應(yīng)該從頭部(2號簇)開始尋找空閑簇|
| FSI_Reserved2 |496 | 12 | 保留區(qū)域,采用0x00覆蓋 |
| FSI_TrailSig | 508 | 4 | 固定值0xAA550000,尾部簽名 |
注意:當扇區(qū)大小大于512字節(jié)時, 剩余空間采用0x00填充
4.7 FAT目錄
FAT目錄分為長文件名目錄(LFN)以及短文件名目錄(SFN),長文件目錄是在短文件名目錄上的一個擴展,具體采用長文件名還是短文件名由讀取FAT文件系統(tǒng)的操作系統(tǒng)決定,如windows;設(shè)置長文件名時短文件名也被設(shè)置,具有兼容性。
此外,有一個很重要的概念:在FAT文件系統(tǒng)上目錄也是一個文件,只是此文件的屬性不一樣而已。
在所有目錄中,有一個比較特殊的是根目錄,且根目錄作為頂層目錄必須存在。
在FAT12/16系統(tǒng)中,根目錄不是一個文件,且放在根目錄區(qū),根目錄的最大條目數(shù)由 BPB_RootEntCnt 參數(shù)指示;
在FAT32系統(tǒng)中,根目錄與子目錄沒有什么區(qū)別,且根目錄的起始簇由 BPB_RootClus 參數(shù)指示。
根目錄與子目錄的另外一個區(qū)別是,根目錄不包含 . .. 此兩個點目錄,且它可以包含卷標(具有ATTR_VOLUME_ID屬性的條目)
關(guān)于目錄結(jié)構(gòu)的第一個字段 DIR_Name 的第一個元素 DIR_Name[0] 在目錄表中有著特殊作用,如下:
當此值為 0xE5 時,代表此目錄條目未被使用(或已廢棄)
當此值為 0x00 時,也代表此目錄條目未被使用;此外還提示后續(xù)目錄條目也未被使用,因為后續(xù)的目錄條目 DIR_Name[0] 都會是 0x00
如果文件名的第一個字符為 0xE5 這個特殊值,則使用 0x05 替代。
這么設(shè)計的意義是什么呢?將 DIR_Name[0] 用作特殊字符,其目錄在于方便文件刪除!當我們刪除一個文件的時候,文件系統(tǒng)并不會將此文件所對應(yīng)的數(shù)據(jù)全部刪除,因為那樣太費時間了,也沒有必要,而是直接將對應(yīng)文件的目錄項中的 DIR_Name[0] 修改為 0xE5 即可!
關(guān)于文件名字段 DIR_Name,在FAT文件系統(tǒng)中還有如下規(guī)定:
DIR_Name 字段的11字節(jié)的文件名分為兩個部分:8 字節(jié)的主文件名 + 3字節(jié)的擴展名;
文件名中主文件名與擴展名中間的 . 被省略,不在此記錄
如果主文件名長度不夠,小于8字節(jié),則使用 0x20 空格填充
用于設(shè)置文件名的字符也有限制,支持的字符有 ==0~9 A~Z ! # $ % & ‘ ( ) - @ ^ _ ` { } ~==
主文件名和擴展名中的(a~z)ASCII字符都會被轉(zhuǎn)化成大寫字符保存
以下為文件名存儲示例:
4.7.2 LFN長文件名
長文件名是文件名的另外一種存儲方式,由于SFN短文件名具有長度、字符等限制,在一些場景下不能很好的滿足需求,因此就需要使用到長文件名,關(guān)于長文件名的具體內(nèi)容如下:
長文件名是一個具有特殊屬性的目錄條目。長文件名目錄屬性 DIR_Attr 字段的值 ATTR_LONG_NAME = (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) = 0x0F;
關(guān)于長文件名的目錄屬性如下:
| 字段名 | 偏移 | 大小 | 描述 |
| — | — | — | — |
| LDIR_Ord | 0 | 1 | 序號(1-20),用來表示此條目屬于長文件名序列條目中的第幾條。且長文件名序列首條條目的值應(yīng)& 0x40以進行標識! |
| LDIR_Name1 | 1 | 10 | 長文件名 第1 ~ 第5 字符(注意此處一個字符占兩個字節(jié)) |
| LDIR_Attr | 11 | 1 | 長文件名屬性,此值永遠為 ATTR_LONG_NAME 0x0F
| LDIR_Type | 12 | 1 | 類型,必須為0 |
| LDIR_Chksum | 13 | 1 | 和校驗 |
| LDIR_Name2 | 14 | 12 | 長文件名 第6 ~ 第11 字符(注意此處一個字符占兩個字節(jié)) |
| LDIR_FstClusLO | 26 | 2 | 必須為0 |
| LDIR_Name3 | 28 | 4 | 長文件名 第12 ~ 第13 字符(注意此處一個字符占兩個字節(jié)) |
關(guān)于長文件名,有以下幾點重要概念:
一個文件一定有短文名SFN,但不一定有長文件名LFN
長文件名LFN字段中==僅包含文件名信息==,不包含其他內(nèi)容,其他內(nèi)容需要通過短文件名SFN查看
如果一個文件既有長文件名也有短文件名,則長文件名是其主要名字,而短文件名則為附加名字
==長文件名LFN條目在對應(yīng)的短文件名SFN條目前面==
一個文件的長文件名最長255字符,對應(yīng)最多20個長文件名LFN條目
長文件名簡單理解起始就是存儲一個字符串,因此沒有類似SFN的限制,允許有空格、支持大小寫、允許多個.符號等
LFN條目文件名長度不夠,仍然采用0x20填充
下圖是官方關(guān)于一個名為 “MultiMediaCard System Summary.pdf” 的長文件名在flash上的長文件名條目,如下所示,一眼沒看明白也沒關(guān)系,后文有實例說明,對長文件名有概念了就行!
關(guān)于長文件名的checksum字段和計算,算法如下:
uint8_t create_sum (const DIR* entry)
{
int i;
uint8_t sum;
for (i = sum = 0; i < 11; i++) { /* Calculate sum of DIR_Name[] field */
sum = (sum >> 1) + (sum << 7) + entry->DIR_Name[i];
}
return sum;
}
4.7.3 LFN系統(tǒng)對于SFN的兼容
在使用LFN長文件名的系統(tǒng)中,會自動生成SFN短文件名已確保此文件在短文件名的文件系統(tǒng)中可使用。同時為了防止生成的短文件名沖突,SFN的生成采用 名稱+數(shù)字后綴+擴展 的格式,同時采用以下規(guī)則生成SFN:
小寫自動轉(zhuǎn)大寫
如果存在空格,則刪去空格,設(shè)置有損轉(zhuǎn)換標識
已.開頭的文件刪除頭部的.,并設(shè)置有損轉(zhuǎn)換標識
存在多個.的文件名,僅保留最后一個作為文件名與擴展的分隔,并設(shè)置有損轉(zhuǎn)換標識
其他不支持的字符,采用_代替,并設(shè)置有損轉(zhuǎn)換標識
文件名如果是Unicode編碼,則轉(zhuǎn)化為ANSI/OEM編碼;不能轉(zhuǎn)換的字符采用_代替,并設(shè)置有損轉(zhuǎn)換標識
長度超過8字節(jié)的部分,截斷,并設(shè)置有損轉(zhuǎn)換標識
擴展名字段超過3字節(jié)的,截斷,并設(shè)置有損轉(zhuǎn)換標識
有損轉(zhuǎn)轉(zhuǎn)換標識為:~,ASCII值為0x7E,十進制126
示例如下:
至此,F(xiàn)AT文件系統(tǒng)的理論部分已經(jīng)描述完了,接下來我們繼續(xù)使用winhex對數(shù)據(jù)進行分析。
-
驅(qū)動器
+關(guān)注
關(guān)注
52文章
8112瀏覽量
145844 -
SD卡
+關(guān)注
關(guān)注
2文章
558瀏覽量
63754 -
Flash存儲
+關(guān)注
關(guān)注
0文章
38瀏覽量
8275 -
FatFS文件系統(tǒng)
+關(guān)注
關(guān)注
0文章
12瀏覽量
7514
發(fā)布評論請先 登錄
相關(guān)推薦
評論