FAT32文件系統學習(1) —— BPB的理解

FAT 32 文件系統學習

 

一、本文的目標

       本文將經過實際讀取一個FAT32格式的U盤來簡單瞭解和學習FAT32文件系統的格式。雖然目前windwos操做系統的主流文件系統格式是NTFS,可是FAT32因爲其兼容性緣由,仍是有必定的學習價值。爲了能作出一個窗體程序提供直觀的感受,本文的代碼採用c#編寫,對應的c++代碼也會附上。c++

二、本文目錄

一、本文的目標編程

二、什麼是FAT32c#

2.1 FAT32的構成windows

三、引導區api

3.1 讀取引導扇區安全

3.2 BPB參數app

3.3 程序實現異步

二、什麼是FAT32

      FAT32是Windwos系統硬盤格式分區的一種。這種格式採用32位的文件分配表,使其對磁盤的管理能力大大加強,突破了FAT16對配一個分區的容量只有2GB的限制。雖然目前已被更優異的NTFS分區格式所取代[1]。其實說白了就是FAT表的每一項長度都是32位,因此叫作FAT32。至於每一項存放的內容是什麼,下面的內容會慢慢進行分析。函數

  • FAT32的構成

       FAT32 文件系統將邏輯盤的空間劃分爲三部分,依次是引導區 (BOOT區)文件分配表區(FAT區)數據區(DATA區)[2]。引導區和文件分配表區又合稱爲系統區。本文將簡單學習引導區的內容,文件分配表區和數據區將在下一篇文章中學習。學習

 三、引導區

  • 讀取引導扇區

       引導區從第一扇區開始,保存了每一個扇區的字節數,一個簇的扇區數,FAT表的起始位置,FAT表的個數以及FAT表的扇區數等信息。以後還留有若干保留扇區。首先咱們先看一下如何從一個U盤當中讀取引導區(這裏只讀取第一個扇區,接下來的讀取方法相同)。爲了直接讀取磁盤的邏輯扇區,咱們須要用到windows api當中的幾個函數,分別是CreateFile(這裏用來建立磁盤的句柄),ReadFile(這裏用於讀取磁盤扇區)。首先來看一下這兩個函數的定義:

1 HANDLE WINAPI CreateFile(
2   _In_      LPCTSTR lpFileName,                          // 要打開的文件的名或設備名。
3   _In_      DWORD dwDesiredAccess,                       // 指定類型的訪問對象。
4   _In_      DWORD dwShareMode,                           // 文件共享模式
5   _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // 定義了文件的安全特性
6   _In_      DWORD dwCreationDisposition, 
7   _In_      DWORD dwFlagsAndAttributes, 
8   _In_opt_  HANDLE hTemplateFile                         // 返回句柄
9 );

       這個函數在msdn上能夠查到,這裏須要說明一下的是,dwShareMode須要指定爲FILE_SHARE_WRITE才能讀取扇區的數據(這裏是爲何我也不太清楚爲何,但願高人指教)。dwCreationDisposition須要制定爲OPEN_EXISTING ,表示文件必須已經存在,由設備提出要求。函數如執行成功,則返回文件句柄。不然返回的句柄 = INVALID_HANDLE_VALUE表示出錯,會設置GetLastError。具體失敗緣由能夠查詢ErrorCode。

       第二個函數是ReadFile,其定義以下:

1 BOOL ReadFile(
2     HANDLE hFile,               //文件的句柄
3     LPVOIDl pBuffer,            //用於保存讀入數據的一個緩衝區
4     DWORD nNumberOfBytesToRead, //要讀入的字節數
5     LPDWORD lpNumberOfBytesRead,//指向實際讀取字節數的指針
6     LPOVERLAPPED lpOverlapped
7     //如文件打開時指定了FILE_FLAG_OVERLAPPED,那麼必須,用這個參  數引用一個特殊的結構。
8     //該結構定義了一次異步讀取操做。不然,應將這個參數設爲NULL
9 );

       該函數用於讀取文件,這裏指的是讀取U盤扇區。其中lpOverlapped設爲NULL便可。須要特別注意的是,因爲磁盤是以扇區爲單位進行讀寫的,因此這裏讀取的字節數必須是512的倍數!其餘參數註釋寫的很明白,這裏就再也不解釋了。配合SetFilePointer函數能夠讀取指定起始位置上指定字節的數據。

       首先先來看一下用c++是如何讀取引導扇區的數據的。

 1     // 筆者的U盤盤符爲G
 2     WCHAR szDiscFile[] = _T("\\\\.\\G:"); 
 3     // 打開設備句柄
 4     HANDLE hDisc = CreateFile(szDiscFile, GENERIC_READ,  FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 5     if (hDisc == INVALID_HANDLE_VALUE)
 6     {
 7         // 打開設備失敗
 8         return 0;
 9     }
10     // 從第一個扇區起始位置開始讀取
11     SetFilePointer(hDisc, 0, 0, FILE_BEGIN);
12     // 須要讀取字節數
13     DWORD dwNumber2Read = 512;
14     // 實際讀取的字節數
15     DWORD dwRealNumber;
16     // 分配緩衝區
17     char* buffer = new char[512];
18     bool bRet = ReadFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL);
19 
20     // 掃尾工做,釋放緩衝區,關閉句柄
21     delete[] buffer;
22     CloseHandle(hDisc);

        若是咱們在21行處下各斷點的話能夠看到buffer在內存中的數據,這裏爲了方便,筆者直接把這512個字節的數據保存到了文件中,用二進制文件讀取軟件打開來看了下,部分數據以下圖所示:

  • BPB參數

       好了,接下來重點來了。首先,最開始的3各字節的數據分別是跳轉指令空指令,由於在彙編當中0xEB是跳轉指令,0x58是跳轉的地址,而0x90則是空指令。至於爲何要在這裏放上一句跳轉指令呢,這個還得從啓動區開始講起,爲了節約篇幅,我就簡單介紹一下:通常第一個扇區叫作啓動區,cpu把扇區當中的數據看成指令來執行,當讀取到EB 58 這個指令時,遍跳轉到0x58這個地址並繼續讀取指令來執行,而0x58地址以後的內容一般都是載入操做系統的指令。若是但願知道詳細內容的讀者不妨去看一下《30天自制操做系統》這本書,第一天結尾部分有很詳細的說明。總之這邊的話FAT32規定這個3各字節的內容必須是EB 58 90,只要記住就好了(笑)。(如1L所說,EB 58 90 對應彙編代碼即爲JUMP 0x58; NOP;)。

       而從0x03~0x0A這8個字節的數據表示OEM,這裏即爲「MSDOS5.0」。

       咱們把從0x000B開始的79個字節的數據叫作BPB(BIOS Paramter Block),關於BPB的詳細說明請參見下表[5]

BPB參數信息
偏移量 字節數 含義
0x00B 2 每扇區字數 0x0200
0x00D 1 每簇扇區數 0x08
0x00E 2 保留扇區數 0x03F8
0x010 1 FAT個數 0x02
0x011 2 根目錄項數,FAT32以突破該限制,無效  0x0000 
0x013 2 扇區總數,小於32M使用  0x0000 
0x015 1 存儲介質描述負  0x0F8 
0x016 2 每FAT表佔用扇區數 ,小於32M使用 0x0000 
0x018 2 邏輯每磁道扇區數  0x003F 
0x01A 2 邏輯磁頭數  0x00FF
0x01C 4 系統隱含扇區數  0x00000080
0x020 4 扇區總數,大於32M使用  0x00784F80
0x024 4 每FAT表扇區數,大於32M使用  0x00001E04 
0x028 2 標記  0x0000
0x02A 2 版本 (一般爲零) 0x0000
0x02C 4 根目錄起始簇  0x00000002 
0x030 2 Boot佔用扇區數  0x0001 
0x032 2 備份引導扇區位置  0x0006
0x034 14 保留 14個字節的0x00 
0x042 1 擴展引導標記  0x29 
0x043 4 序列號  0x6A9C4125 
0x047 10 卷標 轉成字符即「NO NAME」
0x052 8 文件系統  轉成字符即「FAT32」 

 

        我來解釋一下其中的幾個參數。首先是保留扇區數,它能夠理解爲是FAT表的起始位置。咱們能夠先來看一下下面這張圖,有助於更好的理解保留扇區數的意思。

       能夠看到引導扇區後面緊跟這若干保留扇區,至於保留扇區的做用會在下一篇中分析,這裏先跳過。而保留扇區的後面緊跟着的是FAT1和FAT2。因此FAT1表的起始地址是(引導扇區+保留扇區)*扇區字節數?不對。這裏有個須要注意的地方是,保留扇區數這個參數其實已經包含了引導扇區了,因此在計算FAT1表位置的時候直接經過保留扇區數這個參數來計算偏移就好了。這一點須要特別注意。(這裏筆者看了幾篇文獻的說法不一,有說須要加上保留扇區的,有說不用加的,多是版本不同的關係。可是筆者親自實踐以後發現是不須要加上的。)

       至於FAT表留到下一篇再講,這裏說明一下爲何FAT會有兩張。文件分配表區共保存了兩個相同的文件分配表,由於文件所佔用的存儲空間(簇鏈)及空閒空間的管理都是經過FAT實現的,FAT如此重要,保存兩個以便第一個損壞時,還有第二個可用[4]。這樣FAT表個數這個參數也解釋了。

  • 程序實現

        爲了用窗體程序直觀的顯示各個參數,接下來把上面的程序改寫爲c#。衆所周知,c#調用系統函數大多都須要靠間接調用c的動態庫來實現,這裏的CreateFile和ReadFile也不例外。下面咱們先編寫一個FileReader類來提供這些系統api調用。部分代碼以下,完整的FileReader點我下載

class FileReader
{
  [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
    static extern unsafe System.IntPtr CreateFile
    (
        string FileName,          // file name
        uint DesiredAccess,       // access mode
        uint ShareMode,           // share mode
        uint SecurityAttributes,  // Security Attributes
        uint CreationDisposition, // how to create
        uint FlagsAndAttributes,  // file attributes
        int hTemplateFile         // handle to template file
    );
  public bool Open(string FileName) { // open the existing file for reading handle = CreateFile ( FileName, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ); if (handle != System.IntPtr.Zero) { return true; } else { return false; } }

        因爲本文的重點不是學習c#窗體編程,因此略過這部分,直接經過調用FileReader提供的系統API並編寫窗體程序,效果以下圖所示(本程序參考[3]),須要完整工程的讀者能夠點我下載,請我VS2012及以上打開。

       好了,今天這篇文章就先寫到這邊。因爲筆者才疏學淺,對於FAT32也是剛開始學習,若是有錯誤的地方歡迎批評指正。同時這也是我第一次發隨筆,若是排版等方面有不妥的地方也歡迎提出。接下來會繼續學習接下去的FAT表區和數據區並繼續更新接下來的學習心得。

 

參考文獻:

一、http://baike.baidu.com/view/45233.htm?fr=aladdin

二、FAT32文件格式 http://blog.csdn.net/shrekmu/article/details/5950414

三、讀寫U盤(FAT32)引導扇區 http://blog.csdn.net/zhanglei8893/article/details/5912903

四、F​A​T​3​2​文​件​系​統​格​式​詳​解 http://wenku.baidu.com/link?url=zrGv8nld-bc-7KT_TKbo2vWplaiIHhmJ9_ydRZBZdZ4zy8odQFwS6komz2gz1AHX36T_EN1CKZ_16d19upW9pDauno6zEmpw10wlTSTwcoi

五、基​於​U​盤​F​A​T​3​2​文​件​系​統​的​分​析 http://wenku.baidu.com/link?url=cIKgrwV66y4CoyuOEB1-OhjRY9tnXtIAoZuYEwDCjxbyRomSIiJgBAXGxq6LudfwuopUpYhiVd8TjxrBFoVyPs0NX3OqbnoWjyn4ZAx60Wi

相關文章
相關標籤/搜索