magicchip的笔记 https://bbs.21ic.com/?478556 [收藏] [复制] [RSS]

日志

FAT12/FAT16 文件系统简价

已有 1299 次阅读2011-6-17 13:53 |个人分类:FAT文件系统|系统分类:嵌入式系统| 嵌入式系统, FAT, FAT16, FAT32, 文件系统

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


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)