基于stm32f103zet6的FAT16文件系統(tǒng)學習1(初識FAT16)
有了之前讀寫block的基礎(chǔ)之后,準備弄個文件系統(tǒng),之前沒有接觸過這東西,所以有很多都暈暈的,但是看到fat的源代碼之后還是挺有信心的,因為之前一直過uboot,所以這個文件當然是小巫見大巫了。首先來分析一下對應(yīng)我的SD的FAT16的相關(guān)信息吧(暫且就這么稱吧,因為我也不是很了解)。
一、引導扇區(qū)段
拿比較簡單的FAT16文件系統(tǒng)來分析,格式化為FAT16,然后使用Winhex軟件打開我的磁盤驅(qū)動器。先貼上一張圖
這上面可以發(fā)現(xiàn)很多有用的信息,首先我們了解一下基本知識,對于我的SD卡來說,從上面的信息可以看出:
1、一個扇區(qū)定為512字節(jié)。
2、啟動扇區(qū)為0扇區(qū),同時這也是物理扇區(qū)0,但是,從上面可以看出,我的SD卡是沒有MBR(主引導記錄區(qū))的,所以這個物理扇區(qū)0也就是我的DBR(系統(tǒng)引導扇區(qū)),也就是所謂的邏輯扇區(qū)0吧(這是我個人的理解)
補充一下:如果有MBR的,那么MBR為訪問的第一個扇區(qū),該扇區(qū)必須負責找到DBR
3、那么下面來分析一下這個DBR吧??聪旅嬉粡埍恚涂梢灾浪亩x了。下面這張表實在網(wǎng)上找的,所以和我的SD卡描述的不一樣,我把我的SD描述的情況補充在后面。
自然從這個表上面我們可以獲取如下主要信息:
每扇區(qū)字節(jié)數(shù):0x0200 = 512字節(jié)
每簇扇區(qū)數(shù): 0x20 = 32扇區(qū)
保留扇區(qū)數(shù): 1扇區(qū)
FAT表份數(shù): 0x02 = 2份
根目錄項數(shù): 0x0200 = 512,所以做多能存放的文件或者文件夾數(shù)目 = 512.
每個FAT表所占的扇區(qū):0x00f3 = 243個扇區(qū)
FAT表所在的分區(qū)前面隱藏的扇區(qū)數(shù):0x00 = 0,再次驗證了我之前的猜測。沒有MBR的,只有DBR。
卡的容量(總的扇區(qū)數(shù)): 0x1e5c00 =1989632 ,那么換算成M就是:1989632 * 512B = 971.5M
卡的ID: 0x980b5f1f
FilesysType :0x31544146就是FAT16的ASCII碼。
可執(zhí)行代碼:從0x3c 開始的 347和字節(jié)都是可執(zhí)行代碼。
繼續(xù)看表格。
DBR的偏移 0x5A開始的數(shù)據(jù)為引導代碼。這是由偏移 0x00 開始的跳轉(zhuǎn)指令所指向的。 所列出的偏移 0x00~0x02 的跳轉(zhuǎn)指令"EB 3c 90"清楚地指明了引導代碼的偏移位置。jump 3cH加上跳轉(zhuǎn)指令所需的位移量,即開始于 0x3c。此段指令在不同的操作系統(tǒng)上和不同的引導方式上,其內(nèi)容也是不同的。從頭到尾梳理一遍,我們的FAT16文件系統(tǒng)框架就是這樣:
引導扇區(qū)段
字節(jié)位移字節(jié)長度字段名稱
0x003跳轉(zhuǎn)指令
0x038OEMID
0x0b2BPB
0x2424擴展BPB
0x3c448引導代碼
0x1fe4扇區(qū)結(jié)束標識符
二、關(guān)于FAT表
1、FAT 表(File Allocation Table 文件分配表),是 Microsoft 在 FAT 文件系統(tǒng)中用于磁盤數(shù)據(jù)(文件)索引和定位引進的一種鏈式結(jié)構(gòu)。假如把磁盤比作一本書,F(xiàn)AT 表可以認為相當于書中的目錄,而文件就是各個章節(jié)的內(nèi)容。但FAT 表的表示方法卻與目錄有很大的不同。在 FAT 文件系統(tǒng)中,文件的存儲依照 FAT 表制定的簇鏈式數(shù)據(jù)結(jié)構(gòu)來進行。同時,F(xiàn)AT 文件系統(tǒng)將組織數(shù)據(jù)時使用的目錄也抽象為文件,以簡化對數(shù)據(jù)的管理。
2、FAT16 文件系統(tǒng)從根目錄所占的 32 個扇區(qū)之后的第一個扇區(qū)開始以簇為單位進行數(shù)據(jù)的處理,這之前仍以扇區(qū)為單位。對于根目錄之后的第一個簇,系統(tǒng)并不編號為第 0 簇或第 1 簇 (可能是留作關(guān)鍵字的原因吧),而是編號為第 2簇,也就是說數(shù)據(jù)區(qū)順序上的第 1 個簇也是編號上的第 2 簇
3、FAT 文件系統(tǒng)之所以有 12,16,32 不同的版本之分,其根本在于 FAT 表用來記錄任意一簇鏈接的二進制位數(shù)。以 FAT16 為例,每一簇在 FAT 表中占據(jù) 2字節(jié)(二進制 16 位)。所以,F(xiàn)AT16 最大可以表示的簇號為 0xFFFF(十進制的65535),以 32K 為簇的大小的話,F(xiàn)AT32 可以管理的最大磁盤空間為:32KB×65535=2048MB,這就是為什么FAT16 不支持超過 2GB 分區(qū)的原因。
FAT表記錄了磁盤數(shù)據(jù)文件的存儲鏈表,對于數(shù)據(jù)的讀取而言是極其重要的,以至于Microsoft為其開發(fā)的FAT文件系統(tǒng)中的FAT表創(chuàng)建了一份備份,就是我們看到的FAT2。FAT2與FAT1的內(nèi)容通常是即時同步的,也就是說如果通過正常的系統(tǒng)讀寫對FAT1 做了更改,那么FAT2 也同樣被更新。如果從這個角度來看,系統(tǒng) 的這個功能在數(shù)據(jù)恢復時是個天災(zāi)
4、FAT 表實際上是一個數(shù)據(jù)表,以 2 個字節(jié)為單位,我們暫將這個單位稱為FAT 記錄項,通常情況其第 1、2 個記錄項(前 4 個字節(jié))用作介質(zhì)描述。從第三個記錄項開始記錄除根目錄外的其他文件及文件夾的簇鏈情況。根據(jù)簇的表現(xiàn)情況 FAT 用相應(yīng)的取值來描述,特殊情況如下:
5、下面開始分析一個FAT表,我給SD裝入一個文件,名為BingGe.bin
6、如上圖,F(xiàn)AT表以"F8 FF FF FF" 開頭,此2 字節(jié)為介質(zhì)描述單元,并不參與FAT表簇鏈關(guān)系。可以看出是標識符和第一簇已被占用的意思。
它的第一個簇的地址是0x0002。這個地址從哪里得來的要看后面的內(nèi)容了,暫且就把它當已知條件吧。這也就是說,在SD卡的第2個簇里邊存放著dssd.bin的第1個16K數(shù)據(jù),那么它的第二個16K放在哪里呢,我們要看FAT表,每2個簇對應(yīng)于FAT表中的第4,5個字節(jié),里邊的內(nèi)容為0003接下來的第4、5字節(jié)表示 0x0003,這是第2簇,
第6、7字節(jié)表示0x0004,這是第3簇
。。。
。。。
可以發(fā)現(xiàn)總共是到0x000b結(jié)束的。
所以可以推斷出這個文件占用空間是9個簇,那么大小= (10*32*512) =163840(簇注意結(jié)束符才算最后一個簇),那么我們截張圖看一下,占用大小是多少
顯然占用空間也是163840,完全和我們計算的一樣。那么,我們繼續(xù)跟蹤一下,既然文件是按照簇為單位進行存儲的,那么我們的一個簇是16KB,暫且不管第2個簇是什么內(nèi)容。因為我們文件中的內(nèi)容是從第2簇開始的,第2簇存放的是0003,數(shù)據(jù)0003表示接下來的簇是第3簇,以此類推,可以知道第9簇里面的內(nèi)容是000b,接下來是第b簇也就是結(jié)束簇,至此完成FAT表的初步分析。
三、有關(guān)根目錄
根目錄區(qū)里面放的東西就是根目錄下所見的東西,根據(jù)對引導扇區(qū)的分析,我們可以找到根目錄區(qū)在第448扇區(qū)內(nèi),如何知道的呢?看一張圖示表
紅色箭頭部分,表示保留扇區(qū),這里我的SD卡是由兩個保留扇區(qū)的。所以我們的根文件目錄扇區(qū) = (FAT*2)+保留+引導扇區(qū) = 446+1+1 = 448扇區(qū),從0開始,也就是第447扇區(qū)。那么我們的根文件目錄就是第448扇區(qū)了。其實,當我們了解了整個結(jié)構(gòu)之后,就能夠通過winhex來,整體把握這個FAT的結(jié)構(gòu)了。
1、開始貼上根目錄里面的內(nèi)容
FAT16和FAT32每個文件名都占32個字節(jié),這里放的是短文件名。但FAT16的根目錄區(qū)只有32個扇區(qū),計算一下,每個扇區(qū)512字節(jié),共32個扇區(qū),而每個文件要占用32個字節(jié),很顯然,根目錄只能放512個文件了。我們對照這下面的這個表格來提取信息
就看最前面的32字節(jié)吧,它表示了一個文件(或文件夾),現(xiàn)在對它分析一下。前11個字節(jié)是文件名。從后面的ASCII表中可以看出,它就是我寫進去的那個名為BingGe.bin。至于為什么會出現(xiàn)那個A,我也不得而知了。第0x0B個字節(jié)內(nèi)容為0x20,可以知道它的屬性為存檔,這與我們從windows中觀察到的它的屬性是一致的。
0x18~0x19 中的日期=(年份-1980)*512+月份*32+日。得出的結(jié)果換
算成 16 進制填入即可。也就是:0x18 字節(jié) 0~4 位是日期數(shù);0x18 字節(jié) 5~7 位
和 0x19 字節(jié) 0 位是月份;0x19 字節(jié)的 1~7 位為年號,原定義中 0~119 分別代
表 1980~2099,目前高版本的Windows允許取 0~127,即年號最大可以到 2107
年。
那么我看看我們的修改日期:3f 89 = 0011111 1100 01001,那么日期為9 ,月份為12月,年份為31+1980 = 2011年,所以修改日期應(yīng)該為2011.12.9,再看看我們的文件
果然是沒有錯的。接著看目錄是怎樣訪問的。
可以看到我們的一個文件夾地址是0x0c那么,跳轉(zhuǎn)到這個簇去看一看就行了。
前面那個項,一個是2E,一個是2E 2E,它倒底是何方神圣,對照ASCII表,它就是一個小點“.”。這個小點什么意思,那第二項就是“..”,有沒有什么啟發(fā)?——DOS!那個
古老的操作系統(tǒng)是怎么訪問文件夾的?cd ..就是返回上一層目錄。難道是它……?沒錯!就是它,一個點代表當前目錄,兩個點代表上級目錄。哈哈??匆幌庐斍澳夸浤且豁棧匆幌滤牡刂?,000A,就是這個目錄。而..對應(yīng)的那一項,分析一下地址。00 00,也就是根目錄。所以就可以利用這里找到上一級目錄,于是就可以實現(xiàn)一級一級目錄的訪問了。到這里根目錄也就初步分析完畢了。接下來準備開始進行初步的移植文件系統(tǒng)了。