|||
FAT文件系统结构
启动扇区与BPB
FAT 数据结构
FAT 目录结构
FAT类型的辨别
--------------------------------------------------------------------------------
FAT文件系统结构
FAT文件系统的总体结构如下:
0——保留区(Reserved Region)
1——FAT区(FAT Region)
2——根目录区(Root Directory Region)
3——文件和目录数据区(File and Directory Data Region)
启动扇区与BPB
BPB(BIOS Parameter Block)是FAT文件系统中的一个重要的数据结构,它位于FAT卷的第一个扇区,这个扇区又被称作“启动扇区”、“保留扇区”等。BPB的C语言描述如下:
view plaincopy to clipboardprint?
typedef struct strBPB{
BYTE BS_jmpBoot[3]; //跳转指令,指向启动代码
BYTE BS_OEMName[8]; //Microsoft操作系统并不在乎
WORD BPB_BytsPerSec; //每扇区字节数
BYTE BPB_SecPerClus; //每簇扇区数,2 的幂数,同时每簇不能超过32K
WORD BPB_RsvdSecCnt; //保留扇区数,FAT12和FAT16为1
BYTE BPB_NumFATs; //卷中FAT表数目,建议为2
WORD BPB_RootEntCnt; //根目录最大项
WORD BPB_TotSec16; //总扇区数,如果大于0X10000的话,用BPB_TotSec32记录
BYTE BPB_Media; //OXF0~0XFF为合法取值,FAT[0]的低字节要写入相同值
WORD BPB_FATSz16; //一个FAT表所占扇区数
WORD BPB_SecPerTrk; //每磁道扇区数
WORD BPB_NumHeads; //磁头数
DWORD BPB_HiddSec; //隐藏扇区数
DWORD BPB_TotSec32; // 总扇区数
BYTE BS_DrvNum; //用于BIOS中断0x13得到磁盘驱动器参数,0x00为软盘,0x80为硬盘
BYTE BS_Reserved; //保留
BYTE BS_BootSig; //扩展引导标志(0X29)
DWORD BS_VolID; //卷标序列号
BYTE BS_VolLab[11]; //磁盘卷标
BYTE BS_FileSysType[8]; //Microsoft不使用此域
}BPB,*PBPB;
typedef struct strBPB{
BYTE BS_jmpBoot[3]; //跳转指令,指向启动代码
BYTE BS_OEMName[8]; //Microsoft操作系统并不在乎
WORD BPB_BytsPerSec; //每扇区字节数
BYTE BPB_SecPerClus; //每簇扇区数,2 的幂数,同时每簇不能超过32K
WORD BPB_RsvdSecCnt; //保留扇区数,FAT12和FAT16为1
BYTE BPB_NumFATs; //卷中FAT表数目,建议为2
WORD BPB_RootEntCnt; //根目录最大项
WORD BPB_TotSec16; //总扇区数,如果大于0X10000的话,用BPB_TotSec32记录
BYTE BPB_Media; //OXF0~0XFF为合法取值,FAT[0]的低字节要写入相同值
WORD BPB_FATSz16; //一个FAT表所占扇区数
WORD BPB_SecPerTrk; //每磁道扇区数
WORD BPB_NumHeads; //磁头数
DWORD BPB_HiddSec; //隐藏扇区数
DWORD BPB_TotSec32; // 总扇区数
BYTE BS_DrvNum; //用于BIOS中断0x13得到磁盘驱动器参数,0x00为软盘,0x80为硬盘
BYTE BS_Reserved; //保留
BYTE BS_BootSig; //扩展引导标志(0X29)
DWORD BS_VolID; //卷标序列号
BYTE BS_VolLab[11]; //磁盘卷标
BYTE BS_FileSysType[8]; //Microsoft不使用此域
}BPB,*PBPB;
启动扇区的最后两个字节必须为0XAA55。
FAT 数据结构
接下来一个重要的数据结构就是 FAT 表(File Allocation Table),它和数据区的簇号一一对应。FAT 表项的大小与 FAT 类型有关,FAT12 的表项为 12-bit ,FAT16 为16-bit 。FAT 表项内容的意义如下图:
FAT目录结构
这个结构我们就可以用 C 语言来描述了,先看代码:
view plaincopy to clipboardprint?
typedef struct strDirEntry {
char Name[11]; // 文件名8字节,扩展名3字节
unsigned char Attributes; // 文件属性
unsigned char Reserved[10]; // 保留未用
FAT_TIME LastWriteTime; // 文件最后修改时间
FAT_DATE LastWriteDate; // 文件最后修改日期
unsigned short FirstCluster; // 文件的第一个簇号
unsigned long FileSize; // 文件长度
} DirEntry, *PDirEntry;
typedef struct strDirEntry {
char Name[11]; // 文件名8字节,扩展名3字节
unsigned char Attributes; // 文件属性
unsigned char Reserved[10]; // 保留未用
FAT_TIME LastWriteTime; // 文件最后修改时间
FAT_DATE LastWriteDate; // 文件最后修改日期
unsigned short FirstCluster; // 文件的第一个簇号
unsigned long FileSize; // 文件长度
} DirEntry, *PDirEntry;
第二个域 Attribute 指明了文件的属性,一个目录项有如下属性:
view plaincopy to clipboardprint?
#define DIRENT_ATTR_READ_ONLY 0x01
#define DIRENT_ATTR_HIDDEN 0x02
#define DIRENT_ATTR_SYSTEM 0x04
#define DIRENT_ATTR_DIRECTORY 0x10
#define DIRENT_ATTR_ARCHIVE 0x20
#define DIRENT_ATTR_READ_ONLY 0x01
#define DIRENT_ATTR_HIDDEN 0x02
#define DIRENT_ATTR_SYSTEM 0x04
#define DIRENT_ATTR_DIRECTORY 0x10
#define DIRENT_ATTR_ARCHIVE 0x20
关于 FAT_TIME 和 FAT_DATE,我们也可以用C语言描述:
view plaincopy to clipboardprint?
typedef struct strFAT_TIME {
unsigned short DoubleSeconds : 5;
unsigned short Minute : 6;
unsigned short Hour : 5;
} FAT_TIME, *PFAT_TIME;
typedef struct strFAT_DATE {
unsigned short Day : 5;
unsigned short Month : 4;
unsigned short Year : 7; // Relative to 1980
} FAT_DATE, *PFAT_DATE;
typedef struct strFAT_TIME {
unsigned short DoubleSeconds : 5;
unsigned short Minute : 6;
unsigned short Hour : 5;
} FAT_TIME, *PFAT_TIME;
typedef struct strFAT_DATE {
unsigned short Day : 5;
unsigned short Month : 4;
unsigned short Year : 7; // Relative to 1980
} FAT_DATE, *PFAT_DATE;
FAT类型的辨别
FAT12 和 FAT16 的区别在于FAT表项的大小,这只是内在的区别,从外部无法直接进行区分。在 BPB 当中有一个标识 FileSystemType 的域,但是Microsoft并不在意这个域的实际内容。事实上,FAT12 和 FAT16只能通过 FAT 卷中簇的数量来判定,这是检测 FAT 类型的唯一办法,世上不存在数小于 4084 的FAT12 卷,也不存在簇数小于4085 或大于 65524 的 FAT16 卷。如果你坚持要违背这一规则来创建一个 FAT 卷,那么至少 Microsoft 的操作系统不会认同此卷。具体判定方法如下:
view plaincopy to clipboardprint?
unsigned long CntOfClust;
CntOfClust = (BPB_RootEntCnt * 32 + BPB_BytsPerSec - 1) / BPB_BytsPerSec;
//这么大串计算,为保证只入不舍
//计算根目录占用扇区数
CntOfClust += BPB_FATSz16 * BPB_NumFATs;
//BPB_FATSz16 是相对于 FAT32 系统命名的
CntOfClust += BPB_RsvdSecCnt;
CntOfClust -= BPB_TotSec16; //对于 FAT 这个域足够用。
CntOfClust /= BPB_SecPerClus;
if(CntOfClust < 4085)
{
//FAT12
}
else if(CntOfClust < 65525)
{
//FAT16
}
else
{
//FAT32?
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fulgen/archive/2011/04/18/6330785.aspx#structure