Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1879151
  • 博文数量: 376
  • 博客积分: 2147
  • 博客等级: 大尉
  • 技术积分: 3642
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-06 10:47
文章分类

全部博文(376)

文章存档

2019年(3)

2017年(28)

2016年(15)

2015年(17)

2014年(182)

2013年(16)

2012年(115)

我的朋友

分类: 嵌入式

2014-07-25 19:40:32

FAT文件系统整体概述

      

MBR:0扇区,分区记录,不一定每个磁盘都有MBR.

 

DBR:可能位于0扇区,若不在0扇区则由MBR计算得到他的位置,以0XEB开始,记录该分区重要参数

保留扇区:可能是32个扇区,也有可能不是。

第一个FAT表:存储了目录与文件数据的链式存储结构

第二个FAT表:作为第一个FAT的备份,防止损坏

第二簇:第一个目录所在的簇号,以下顺序是第三簇第四簇

第三簇开始:记录了目录和文件数据,存储单位是簇,簇与簇之间不一定联系,链式关系要参照FAT表

。。。。。。。。

 

 

第n簇

 

MBR结构:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

00

02

0C

00

0B

38

F8

B8

89

00

00

00

77

9F

3A

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

00

55

AA

MBR前面的数据全部是启动代码,从第446个字节开始为分区记录0、分区记录1、分区记录2和分区记录3.每个分区记录占16个字节,最后以0x55和0xAA结束。该分区表只有一个分区,所以后边的分区记录都是0.

 

分区记录的16个字节的意义如下:

标识                 长度          介绍                        值

Active             1字节     0x80表示分区有效,0x00表示无效    0x00

StartHeat        1字节     分区的开始头                      0x02

StartCylSec     2字节    开始柱面与扇区                     0x0c  0x00

PartType        1字节    分区的类型                         0x0b

EndHead        1字节    分区的结束头                       0x38

EndCylSec      2字节    结束柱面与扇区                     0xf8  0xb8

StartLBA        4字节     分区的第一个扇区              0x89 0x00 0x00 0x00 (137扇区)

Size               4字节     该分区的大小(扇区的个数)       0x77 0x9f 0x3a 0x00

(说明:数据存储为小端格式:低地址放字节数据)

由以上得知我的磁盘的第一个扇区为0x89即第137个扇区,也就是DBR所在的开始扇区,也就是BPB所在的扇区。磁盘的大小为0x3a9f77即1875M,也就是2G。

 

DBR结构里的BPB结构如下:

DBR里面BPB的内容如下:

标识                 字节数        介绍               值

BytesPerSec    2字节       每扇区字节数         0x00 0x02    512字节

SecPerClus     1字节       每簇扇区数           0x08         8个扇区

RsvdSecCnt    2字节       保留扇区数目         0x26 0x00    38个扇区

NumFATs        1 字节       FAT表数             0x02        2个FAT表

RootEntCnt     2字节    

TotSec16        2字节

Midia              1

FATSz16        2

SecPerTrk      2

NumHeads      2

HiddSec         4

TotSec32       4           总扇区数             0x77 0x9f 0x3a 0x00   

FATSz32        4          一个FAT表的扇区数    0xa1 0x0e 0x00 0x00   3745个扇区

ExtFlags         2

FSVer            2

RootClus        4      第一个目录簇号     0x02     第2簇(前面有第0簇和第1簇)

FSInfo            2

BkBootSec     2

Reserved      12

DrvNum         1

Reserved1    1

BootSig         1

VolID             4

FilSysType   11

FilSysType1    8

由以上还可以计算出以下几个重要参数:

 

BPB所在的扇区BPB_Sector_No就是第一个分区即137扇区

保留扇区数:0x0026即保留扇区数为38.

第一个FAT表所在的扇区FirstFATSector:BPB_Sector_No+保留扇区=137+38=175扇区

一个FAT表的扇区数:0x00000ea1即3745个扇区。

第一个目录的扇区号FirstDirSector=FirstFATSector+FATSz32*2=7665扇区

第一个目录所在的簇号为0x02即第二簇。

每簇扇区数:0x08即8个扇区,每个扇区512字节即4K.

FAT文件系统中,簇是存取数据的最小单元,即4K为最小单元

 

根目录的内容:根目录就是记录了文件和目录的相关记录,描述文件的32个字节含义如下:

 

 

 

标识

deName             8字节     文件名,不足补空格

deExtension       3字节      扩展名,不足补空格

deAttributes       1字节      文件属性10的时候表示子目录(文件夹)

deLowerCase    1字节      固定为0

deCHundredth   1字节       忽略

deTime               2字节      创建时间

deCDate             2字节       创建日期

deADate             2字节       最后访问日期

deHighClust      2字节      文件开始簇的高两个字节

deMTime             2字节       最后修改时间

deMDate             2字节       最后修改日期

deLowCluster   2字节      文件开始簇的低两个字节

deFileSize         4字节       该文件的大小,单位是字节

 

读取文件所需要的参数:文件的名字、文件的属性、文件的开始簇、当前簇、当前扇区、扇区中的偏移量、文件当前到文件开始的偏移量,也就是读到了多少个数据、文件的大小以及文件的名字之类的

 

簇项:记录该簇连接到下一簇的簇地址。比如说文件的开始簇是第四簇,则在第四个簇项则记录文件下一个簇的地址,若文件没有下一簇,则第四簇就是FF FF FF 0F. 以第0个簇项开始计算。一个簇项占用四个字节,一个扇区512个字节,则一个扇区可以记录128个簇项。例如根目录所在的簇是第二簇,则在FAT表的第二簇就记录着根目录所占下一簇的地址,若根目录没有下一个簇,则第二个簇项的值为FF FF FF 0F。假如一个簇项的值为0x00 0x00 0x05 0x05,则可以根据此来计算下一个簇的簇项的位置。下一簇的位置是1285,那么下一个簇项的位置在何处?由1285/128=10,可以知道这个簇项偏离FAT表的第一个扇区有10个扇区。而在该扇区的哪个位置呢?由1285%128=5,所以在该扇区的第五个簇项!

 

当首簇即根目录记录文件和目录项没有空间了,也就是第二簇的八个扇区已经记满,那么首簇通过FAT表链到其他的簇,继续记录文件和目录,这就解决了文件和目录过多的情况。

 

底层接口函数:FAT32_ReadSector( )、FAT32_WriteSector( )

初始化函数void FAT32_Init( struct  FAT32_Init_Arg  *arg) :初始化的目的是从MBR和DBR中读取一些重要的参数装入该结构体中,以备后面使用。

该结构体的成员有:                   

BPB_Sector_No:BPB所在的扇区

Total_Size: 总的容量

FATsetors: FAT表的大小

FirstDirClust: 第一个目录所在的簇

BytersPerSector: 每个扇区的字节数

SectorsPerClust: 每个簇的扇区数

FirstFATsector: 第一个FAT表所在的扇区

FirstDirSector: 第一个簇所在的扇区

 

进入目录函数unsigned long FAT32_Enter_Dir(char *path):目录的路径是一个字符串,比如ab\cd\ef的形式。返回相应目录的开始簇,如果进入目录失败(可能是目录不存在),则会返回0.并且用全局变量temp_dir_cluster记录了最近一级目录的最后簇。

 

寻找下一簇函数unsigned long FAT32_GetNextCluster(unsigned long  LastCluster):函数的功能是获得下一簇的簇号,参数是当前的簇,返回下一簇的簇号。N簇的簇项所在扇区为(N/128)+ FirstFATsector; N簇的簇项在该扇区中的偏移量:N%128

 

打开文件函数unsigned char FAT32_OpenFile(struct FileInfoStruct *pfi, char *path):首先 说明文件的路径形式为a\b\test.txt,返回1表示打开文件成功返回0表示打开文件失败。用“进入目录”函数进入文件/目录项所在的目录。文件的信息结构为:

     FileName:文件名

     FileStarCluster:文件开始簇

     FileCurCluster:文件当前簇

     FileSize:文件大小

     FileCurSector:文件当前扇区

     FileCurPos:文件当前扇区的偏移量

     FileCurOffset:文件当前偏移量

     Rec_Sec: 文件目录项所在的扇区

     nRec: 文件目录项在扇区中的偏移量

    

     FileAttr: 文件属性

     FileCreateTime:文件创建时间

     FileCreateDate:文件创建日期

     FileMTime:文件修改时间

     FileMDate:文件修改日期

     FileaADate:文件访问日期

unsigned char FAT32_Seek_File( struct FileInfoStruct *pfi, unsigned long offset):文件定位函数:返回0说明定位失败返回1说明定位成功,参数是文件当前的信息,定位成功后这些信息将会被修改。

 

unsigned long FAT32_ReadFile(struct FileInfoStruct *pfi, unsigned long offset, unsigned long len, unsigned char *pbuf):文件读取函数:返回实际读取到的字节数,如果返回0说明读取失败。参数FileInfoStruct文件结构体,包含了文件的位置,offset为文件的偏移量,len为要读取数据的长度,如果超过文件长度,读取的实际数据长度是文件大小与偏移量的差值。

pbuf为数据缓冲区,读取到的数据放在其中。

阅读(1812) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~