因爲文件的大小不一樣和不停的增刪操做,同一個文件的數據每每不能完整地存放在磁盤的一段連續的扇區內,而會分紅若干小段,像一條鏈子同樣存放,這種存儲方式稱爲文件的鏈式存儲。爲了實現文件的鏈式存儲,磁盤上必須準確地記錄哪一個文件佔用了哪些扇區,哪些扇區尚未被佔用等信息。用來記錄磁盤中文件如何被分散存儲在不一樣扇區的信息的表格就叫文件分配表(File Allocation Table,簡寫爲 FAT)。能夠採用多種辦法記錄文件佔用存儲單元的信息,FAT 表相應的也有不少種格式,3.5 英寸軟盤採用的是 FAT12 格式。那麼這個 FAT12 格式是怎樣的呢?它的 FAT 表放在哪裏呢?函數
前面說過 3.5 英寸軟盤的 0 柱面、0 磁頭、1 扇區是引導扇區,緊接着引導扇區的就是 FAT 表了,並且是兩個連續的、徹底相同的 FAT 表(之因此要兩個徹底相同的 FAT 表,聽說是爲了備份)。那麼 FAT 表是怎麼起做用的呢?FAT 表中每一個表項的值表明的就是某文件佔用的下一個扇區的序號!若是值大於或等於 4088,則表示當前扇區已是本文件的最後一個扇區(爲何是4088 呢?)。spa
因爲 3.5 英寸軟盤有 2880 個扇區,須要 12 個位(bit)來計數(2^11 = 2047,小於2880),因此每一個 FAT 表項佔 12 bit(這就是 FAT12 名字的由來,2^12 = 4096)。實際上 FAT 表還記錄了一些別的信息:第 1 字節的值表明存儲介質(0f0h表明軟盤,0f8表明硬盤);第 二、3 兩個字節都是 0ffh,表明了FAT文件分配表標識符;從第 4 個字節開始才真正與數據區全部的扇區一一對應。因爲 FAT 表前面 3 個字節佔用了 2 個 序號(3 * 8 / 12 = 2),因此數據區的第 1 個扇區的序號是 2,而不是 0 —— 否則就不是一一對應了。操作系統
那麼究竟是哪一個文件呢?那個文件的第 1 個扇區號又是多少呢?數據區的第一個扇區又是第幾號邏輯扇區呢?答案在磁盤結構的下一部分——根目錄表中。
it
根目錄表位於第二個 FAT 表以後。根目錄表由最多 224 個表項組成(DOS 的規定),每一個表項對應一個文件,記錄了該文件的文件名、文件屬性和佔用的第 1 個扇區號。根目錄表的表項格式是這樣的:io
名稱 | 偏移 | 長度 | 描述 |
DIR_Name | 0 | 11 | 文件名8字節,擴展名3字節 |
DIR_Attr | 0xB | 1 | 文件屬性 |
0xC | 10 | 保留 | |
DIR_WrtTime | 0x16 | 2 | 最後修改時間 |
DIR_WrtDate | 0x18 | 2 | 最後修改日期 |
DIR_FstClus | 0x1A | 2 | 此條目對應的開始扇區號 |
DIR_FileSize | 0x1C | 4 | 文件大小 |
能夠算出來,根目錄表佔用 14 個扇區(最多有 224 個表項,每一個表項佔用 32 字節,224 * 32 / 512 = 14),每一個 FAT 表佔用 9 個扇區(假設每一個 FAT 表佔用 X 個扇區,2 個 FAT 表共佔用 2 * X 個扇區,則((總扇區數 2880 - (引導扇區數 1 + FAT 表佔用扇區數 2 * X + 根目錄表佔用扇區數 14)+ 不對應扇區的文件結尾符數最大 224) * 每項佔用位數 12 / 每字節位數 8 + 存儲其餘信息佔用字節數 3 = FAT 表佔用扇區數 X * 每扇區字節數 512,解方程 x = 9),根目錄表從 19 號邏輯扇區開始(前面有 1 個引到扇區 + 2個 FAT 表 * 每一個 FAT 表佔用 9 個扇區 = 19 個扇區) 。table
題外話,我總以爲有個問題:實際數據扇區數有 2880 - 1 - 2 * 9 - 14 = 2847 個。而 FAT 表項數 (9 * 512 - 3)* 8 /12 = 3070,去掉表明文件結尾符的 224 項,3070 - 224 = 2846,也就是能對應 2846 個數據扇區。這中間差了一個(差的這一個是上面解方程的時候,X 的準確值是 9.0029 引發的)!是否是 3.5 英寸軟盤永遠有一個扇區是 FAT12 文件系統管理不到的,被浪費了的呢?百度
根目錄表後面就是數據區了,顯然數據區從 33 號邏輯扇區開始(引到扇區數 1 + FAT 表佔用扇區數 18 + 根目錄表佔用扇區數 14 = 33)。擴展
如今好辦了,用前兩天寫的讀寫扇區的那個函數,直接經過根目錄表項找到文件的第 1 個扇區,再從 FAT 表中找到其餘的扇區,文件就能被讀寫了!程序
那麼,操做系統又是怎麼知道 FAT12 有 2 個FAT,每一個 FAT 佔用 9 扇區,根目錄表最多有 224 個表項的呢?——由於這些信息都記錄在磁盤第一個扇區裏了!第一個扇區的 512 字節,每一個都有明確的用途,百度一下 FAT12 就能找到下面這個表格:im
名稱 | 偏移 | 長度 | 內容 | 軟盤參考值 |
BS_jmpBoot | 0 | 3 | 跳轉指令,指向程序入口 | jmp _main nop |
BS_OEMName | 3 | 8 | 廠商名 | 本身定義 |
BPB_BytsPerSec | 11 | 2 | 每扇區字節數 | 512 |
BPB_SecPerClus | 13 | 1 | 每簇扇區數 | 1 |
BPB_RsvdSecCnt | 14 | 2 | 保留扇區數(用做引導) | 1 |
BPB_NumFATs | 16 | 1 | FAT 表數 | 2 |
BPB_RootEntCnt | 17 | 2 | 根目錄中能容納文件的最大數量 | DOS爲224 |
BPB_TotSec16 | 19 | 2 | 扇區總數(FAT十二、16 用) | 2880 |
BPB_Media | 21 | 1 | 介質描述符 | 0xF0 |
BPB_FATSz16 | 22 | 2 | 每 FAT 表佔用扇區數 |
9 |
BPB_SecPerTrk | 24 | 2 | 每磁道扇區數 | 18 |
BPB_NumHeads | 26 | 2 | 磁頭數 | 2 |
BPB_HiddSec | 28 | 4 | 隱藏扇區數 | 0 |
BPB_TotSec32 | 32 | 4 | 扇區總數(FAT32 用) | 2880 |
BS_DrvNum | 36 | 1 | 驅動器號 | 0 |
BS_Reserved1 | 37 | 1 | 未使用 | 0 |
BS_BootSig | 38 | 1 | 擴展引導標記 |
0x29 |
BS_VolD | 39 | 4 | 卷標序列號 | 0 |
BS_VolLab | 43 | 11 | 卷標 | 本身定義 |
BS_FileSysType | 54 | 8 | 文件系統類型 | 'FAT12' |
引導代碼 | 62 | 448 | 引導代碼、數據及其餘填充字符 | |
結束標誌 | 510 | 2 | 0xAA55 |