因为文件的大小不一样和不停的增删操做,同一个文件的数据每每不能完整地存放在磁盘的一段连续的扇区内,而会分红若干小段,像一条链子同样存放,这种存储方式称为文件的链式存储。为了实现文件的链式存储,磁盘上必须准确地记录哪一个文件占用了哪些扇区,哪些扇区尚未被占用等信息。用来记录磁盘中文件如何被分散存储在不一样扇区的信息的表格就叫文件分配表(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 |