FAT32文件系统解析

阅读: 评论:0

FAT32⽂件系统解析
⽂件系统(File System)是计算机系统必不可少的组成部分,可以说除了部分结构简单的单⽚机系统之外,⽂件系统是⽀撑每⼀个计算机系统运⾏的最重要的⽀撑,⽆论是操作系统、应⽤程序、⽂档还是⾳视频都是基于⽂件系统的。所以由此可见⽂件系统在计算机上的重要地位。
嵌⼊式系统上有很多场合也需要使⽤⼤容量存储设备,这时候可以直接使⽤存储设备的读写API来进⾏数据的保存和读取,但是这样做的很⼤不⾜是⽆法和电脑系统的⽂件兼容,如果想将电脑系统上的⼀张图⽚或者txt⽂档存⼊嵌⼊式系统使⽤的存储器中去就会很⿇烦,但是如果这个嵌⼊式存储器使⽤的是兼容FAT⽂件系统的存储格式那么⽓与个⼈电脑的⽂件交换就会⼤⼤⽅便。例如⼀般场合使⽤的TF卡,如果直接调⽤读和写函数进⾏TF的存取也不是不可以,但是如果这个TF卡上有FAT⽂件系统的话就可以使⽤读卡器从电脑上直接拷贝⽂件,⼤⼤⽅便了⽂件的交互。
mjpg鉴于⽂件系统的重要性,有必要好好分析⼀下⽂件系统的组成原理,下⾯以当前主流的Windows⽂件系统FAT32为对象,分析⼀下⽂件系统的存储机制。
下⾯是对FAT32⽂件系统的⼀个简要介绍:FAT32 ⽂件系统您⼀定不会陌⽣,最多看到它是在 windows 操作系统⾥,但在⼀些嵌⼊式产品(如⼿机、MP3、MP4 等)中,也能看到它的⾝影。从某种意义上来讲,FAT32⽂件系统是⾮常成功的,使我们可以脱离底层储存设备驱动,更为⽅便⾼效地组织数据。给
单⽚机系统中的⼤容量存储器(如 SD 卡、CF 卡、硬盘等)配以 FAT32 ⽂件系统,将是⾮常有意义的(如创建的数据⽂件可以在 windows 等操作系统中直接读取等)。防盗车牌架
我⼿上有⼀张512MB的TF卡将其插在电脑上使⽤⼆进制查看软件打开TF卡,下⾯是拷贝的前512字节的数据进⾏解说:
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
00000000  EB 58 90 4D 53 44 4F 53  35 2E 30 00 02 08 74 18  ëX.
00000010  02 00 00 00 00 F8 00 00  3F 00 FF 00 00 00 00 00  .....ø..?.ÿ.....
00000020  00 34 0F 00 C6 03 00 00  00 00 00 00 02 00 00 00  .4..Æ...........
00000030  01 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000040  80 01 29 22 BE A5 F6 4E  4F 20 4E 41 4D 45 20 20  €.)"¾¥öNO NAME
00000050  20 20 46 41 54 33 32 20  20 20 33 C9 8E D1 BC F4    FAT32  3ɎѼô
00000060  7B 8E C1 8E D9 BD 00 7C  88 56 40 88 4E 02 8A 56  {ŽÁŽÙ½.|ˆV@ˆN.ŠV
00000070  40 B4 41 BB AA 55 CD 13  72 10 81 FB 55 AA 75 0A  @´A»ªUÍ.r..ûUªu.
00000080  F6 C1 01 74 05 FE 46 02  EB 2D 8A 56 40 B4 08 CD  öÁ.t.þF.ë-ŠV@´.Í
00000090  13 73 05 B9 FF FF 8A F1  66 0F B6 C6 40 66 0F B6  .s.¹ÿÿŠñf.¶Æ@f.¶
000000A0  D1 80 E2 3F F7 E2 86 CD  C0 ED 06 41 66 0F B7 C9  Ñ€â?÷â†ÍÀí.Af.·É
000000B0  66 F7 E1 66 89 46 F8 83  7E 16 00 75 39 83 7E 2A  f÷áf‰Føƒ~..u9ƒ~*
000000C0  00 77 33 66 8B 46 1C 66  83 C0 0C BB 00 80 B9 01  .w3f‹F.fƒÀ.».€¹.
000000D0  00 E8 2C 00 E9 A8 03 A1  F8 7D 80 C4 7C 8B F0 AC  .è,.é¨.¡ø}€Ä|‹ð¬
000000E0  84 C0 74 17 3C FF 74 09  B4 0E BB 07 00 CD 10 EB  …Àt.<ÿt.´.»..Í.ë
000000F0  EE A1 FA 7D EB E4 A1 7D  80 EB DF 98 CD 16 CD 19  î¡ú}ëä¡}€ëߘÍ.Í.
00000100  66 60 80 7E 02 00 0F 84  20 00 66 6A 00 66 50 06  f`€~...… .fj.fP.
00000110  53 66 68 10 00 01 00 B4  42 8A 56 40 8B F4 CD 13  ´BŠV@‹ôÍ.
00000120  66 58 66 58 66 58 66 58  EB 33 66 3B 46 F8 72 03  fXfXfXfXë3f;Før.
网眼通00000130  F9 EB 2A 66 33 D2 66 0F  B7 4E 18 66 F7 F1 FE C2  ùë*f3Òf.·N.f÷ñþÂ
00000140  8A CA 66 8B D0 66 C1 EA  10 F7 76 1A 86 D6 8A 56  ŠÊf‹ÐfÁê.÷v.†ÖŠV
00000150  40 8A E8 C0 E4 06 0A CC  B8 01 02 CD 13 66 61 0F  @ŠèÀä..̸..Í.fa.
00000160  82 74 FF 81 C3 00 02 66  40 49 75 94 C3 42 4F 4F  ‚tÿ.Ã..f@Iu”ÃBOO
00000170  54 4D 47 52 20 20 20 20  00 00 00 00 00 00 00 00  TMGR    ........
00000180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00000190  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001A0  00 00 00 00 00 00 00 00  00 00 00 00 0D 0A 44 69  ..............Di
000001B0  73 6B 20 65 72 72 6F 72  FF 0D 0A 50 72 65 73 73  sk errorÿ..Press
000001C0  20 61 6E 79 20 6B 65 79  20 74 6F 20 72 65 73 74    any key to rest
000001D0  61 72 74 0D 0A 00 00 00  00 00 00 00 00 00 00 00 
000001E0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
000001F0  00 00 00 00 00 00 00 00  AC 01 B9 01 00 00 55 AA  ........¬.¹...Uª
下⾯讲讲最重要的⼀个DBR(DOS BOOT RECORD 操作系统引导记录区)。DBR 是我们进军 FAT32 的⾸道防线。其实 DBR 中的BPB 部分才是这⼀区域的核⼼部分(第12~90 字节为 BPB),只有深⼊详实的理解了 BPB 的意义,才能够更好的实现和操控 FAT32。关于 DBR 在 FAT32 中的地位就不多说了,上⾯的数据中的前90个字节是BPB的主要部分。BPB的C语⾔结构体如下所⽰:
struct FAT32_DBR
{
unsigned char BS_jmpBoot[3];  //跳转指令 offset: 0
unsigned char BS_OEMName[8];  //原始制造商 offset: 3
unsigned char BPB_BytesPerSec[2]; //每扇区字节数 offset:11
unsigned char BPB_SecPerClus[1];  //每簇扇区数 offset:13
unsigned char BPB_RsvdSecCnt[2];  //保留扇区数⽬ offset:14
unsigned char BPB_NumFATs[1];  //此卷中FAT表数 offset:16
unsigned char BPB_RootEntCnt[2]; //FAT32为0 offset:17
unsigned char BPB_TotSec16[2];  //FAT32为0 offset:19
unsigned char BPB_Media[1];  //存储介质 offset:21
unsigned char BPB_FATSz16[2];  //FAT32为 0 offset:22
unsigned char BPB_SecPerTrk[2];  //磁道扇区数 offset:24
unsigned char BPB_NumHeads[2];  //磁头数 offset:26
unsigned char BPB_HiddSec[4];  //FAT区前隐扇区数 offset:28
unsigned char BPB_TotSec32[4];  //该卷总扇区数 offset:32
unsigned char BPB_FATSz32[4];  //⼀个FAT表扇区数 offset:36
unsigned char BPB_ExtFlags[2];  //FAT32特有 offset:40
unsigned char BPB_FSVer[2];  //FAT32特有 offset:42
unsigned char BPB_RootClus[4];  //根⽬录簇号 offset:44
unsigned char FSInfo[2];  //保留扇区FSINFO扇区数 offset:48
unsigned char BPB_BkBootSec[2];  //通常为6 offset:50
发动机散热器
unsigned char BPB_Reserved[12];  //扩展⽤ offset:52
unsigned char BS_DrvNum[1];  //offset:64
unsigned char BS_Reserved1[1];  //offset:65
unsigned char BS_BootSig[1];  //offset:66
unsigned char BS_VolID[4];  //offset:67
污染处理unsigned char BS_FilSysType[11]; //offset:71
unsigned char BS_FilSysType1[8]; //"FAT32 " offset:82
};
每个字段的⼤⼩和含义都有详细的注释,解析这些数据使是们进⾏⽂件系统探秘的⾸要任务。需要注意的是在BPB中数据是以⼩端模式存储的,所以51单⽚机的⼤端模式下需要进⾏⼤⼩端的转换,⽽⼀般ARM的默认⽅式就是⼩端模式,所以⽆需进⾏转换操作。
简单介绍DBR的BPB之后还需要介绍⼀下FAT表(⽂件分配表)的概念。什么是⽂件分配表呢?顾名思义,就是给⽂件分配存储空间的表,这⾥⾯存放的不是⽂件的数据⽽是⽂件所在的簇的信息,具体下⾯会给出解释。
FAT 表是 FAT32 ⽂件系统中⽤于磁盘数据(⽂件)索引和定位引进的⼀种链式结构。可以说 FAT 表是 FAT32 ⽂件系统最有特⾊的⼀部分,它的链式存储机制也是 FAT32 的精华所在,也正因为有了它才使得数据的存储可以不连续,使磁盘的功能发挥得更为出⾊。
那么FAT 表到底在什么地⽅?它到底是什么样⼦的?这时就要回到刚才的BPB部分了,在BPB中有⼀个字段叫做
BPB_RsvdSecCnt,这个字段是表⽰保留⼭区数⽬,其实就是保留给BPB使⽤的空间的扇区数量,也就是说这个数值表⽰的就是FAT表前⾯的空间⼤⼩,那么FAT表的地址就是这个字段的数值了。其实在⽂件系统中为了保证正确性和稳定性胡设置两个完全相同的FAT表,并且两个FAT是同步的,也就是说对⼀个 FAT 表的操作, 同样地, 也应该在另⼀个 FAT表进⾏相同的操作,时刻保证它们内容的⼀致。这样是为了安全起见,当⼀个FAT 因为⼀些原因⽽遭到破坏的时候,可以从另⼀个 FAT 表进⾏恢复。
FAT 表的内容如下图所⽰:
上图就是⼀个实际的 FAT 表。前 8 个字节“F8 FF FF 0F FF FF FF FF”为FAT32 的 FAT 表头标记,⽤以表⽰此处是 FAT 表的开始。后⾯的数据每四个字节为⼀个簇项(从第 2 簇开始) ,⽤以标记此簇的下⼀个簇号。
上⾯讲了很多, 都是围绕簇这样⼀个词来讲的, 簇⼜是什么?为什么要将它引⼊到 FAT32 ⾥来呢?磁盘上最⼩可寻址存储单元称为扇区, 通常每个扇区为 512 个字节。 由于多数⽂件⽐扇区⼤得多, 因此如果对⼀个⽂件分配最⼩的存储空间, 将使存储器能存储更多数据,这个最⼩存储空间即称为簇。根据存储设备(磁盘、闪卡和硬盘)的容量,簇的⼤⼩可以不同以使存储空间得到最有效的应⽤。在早期的360KB 磁盘上,簇⼤⼩为 2 个扇区(1,024 字节);第⼀批的 10MB 硬盘的簇⼤⼩增加到8个扇区(4,096字节); 现在的⼩型闪存设备上的典型簇⼤⼩是8KB或 16KB。2GB 以上的硬盘驱动器有 32KB 的簇。如果对于容量⼤的存储定义了⽐较⼩的簇的话,就会使 FAT 表的体积很⼤,从⽽造成数据的冗余和效率的下降。
需要指出的是,簇作为 FAT32 进⾏数据存储的最⼩单位,内部扇区是不能进⼀步细分的, 即使⼀个⽂件的数据写到⼀个簇中后, 簇中还有容量的剩余(⾥部扇区没有写满) ,哪怕这个簇只写了⼀个字节,其它⽂件的数据也是不能接在后⾯继续数据的,⽽只能另外没有被占⽤的簇。
那么 FAT 表有多⼤呢?FAT 表中每四个字节表⽰⼀个簇,所以 FAT 表的⼤⼩由实际的簇数来决定。从这⾥也可以看出,如果簇过⼤,就会则 FAT 表⽐较⼩,但会造成空间的浪费,⽽如果簇过⼩,可以减⼩空间的浪费,但会使FAT 表变得臃肿。FAT 表的⼤⼩可以从BPB 参数 BPB_FATSz32读出。
现在知道了FAT表的地址和FAT表的⼤⼩,也知道有两个FAT表就可以计算出第⼀个⽂件夹也就是根⽂件夹的位置,他的位置就在FAT表的正后⽅,计算⽅法如下:
FirstDirSector = FirstFATSector + BPB_NumFATs[0] * FATsectors ,
其中FirstFATSector 表⽰FAT表的位置, BPB_NumFATs[0] 表⽰FAT表的数量,FATsectors 表⽰的是FAT表占⽤的扇区数量。其实根⽬录所在的簇就是第2号簇。计算出了根⽂件夹的位置就可以从根⽂件夹中读取数据。在 FAT32 中其实已经把⽂件的概念进⾏扩展,⽬录同样也是⽂件,根⽬录的地位与其它⽬录是相同的, 因此根⽬录也被看作是⽂件。 既然是⽂件就会有⽂件名,根⽬录的名称就是磁盘的卷标。
下⾯所以说根⽬录⽂件的内容。⾸先⽬录也是⽂件,它可以看做是特殊⽂件,这个⽂件使⽤来存放其他⽂件或⽬录的信息,例如⽂件名、扩展名、属性、创建时间、最后修改时间、⽂件起始簇号、⽂件长度等等。所以我要读取⼀个⽂件信息的时候⾸先要做的就是从⽬录中读取⽂件的信息数据。根据上⾯说的我们已经获取到了根⽬录的地址,那么就可以从根⽬录中读取根⽬录下的⽂件信息。每个⽂件/⽬录在⽬录⽂件中使⽤32个字节的数据表⽰,具体字段如下所⽰:
这样就可以从根⽬录下读取各个⽂件,我们作为试验不设计嵌套⽬录的结构,只在根⽬录下进⾏⽂件查看、读写试验。所以再我的512M的TF卡上根⽬录下有⼀个⽂件,根⽬录的数据如下所⽰:
Offset      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
00400000  42 20 00 49 00 6E 00 66  00 6F 00 0F 00 72 72 00  B .I.
00400010  6D 00 61 00 74 00 69 00  6F 00 00 00 6E 00 00 00 
00400020  01 53 00 79 00 73 00 74  00 65 00 0F 00 72 6D 00  .S.rm.
00400030  20 00 56 00 6F 00 6C 00  75 00 00 00 6D 00 65 00    .V.o.
00400040  53 59 53 54 45 4D 7E 31  20 20 20 16 00 23 BB 58  SYSTEM~1  ..#»X
00400050  7E 49 7E 49 00 00 BC 58  7E 49 03 00 00 00 00 00  ~I~I..¼
00400060  54 45 53 54 20 20 20 20  54 58 54 20 18 23 C0 58  TEST    TXT .#ÀX
00400070  7E 49 81 49 00 00 5A 57  7E 49 05 00 13 20 00 00  ~I.I.. ..
00400080  54 41 4E 47 51 55 41 4E  20 20 20 08 00 00 00 00  TANGQUAN  .....
00400090  00 00 00 00 00 00 DA 58  7E 49 00 00 00 00 00 00  ......Ú
004000A0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004000B0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004000C0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004000D0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004000E0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004000F0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................聚乙烯醇树脂
00400130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400160  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
00400190  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004001A0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004001B0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004001C0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004001D0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004001E0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
004001F0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
我们可以看到在根⽬录下的0x60到0x7F处表⽰的就是根⽬录下的⽂件,0x80到0x9F处则表⽰的是根⽬录。前⾯的两个⽂件信息表⽰的可能是⼀些隐藏的⽂件,具体我也没了解是什么。反正⾄此已经可以从FAT32⽂件系统中成功获取根⽬录下的⽂件的信息,下⼀步就是根据这个⽂件的信息寻⽂件存储的位置,读取⽂件内容。
32个字节的⽂件信息已经给的很明确了,确定了⽂件的其实簇号之后就可以进⼊FAT表中寻那个簇以及⽂件的簇链,根据⽂件长度字段可以知道⽂件占⽤多少个簇,其实根据簇的链式存储结果就可以知道⽂件占⽤的簇数⽬,但是并不知道⽂件在最后⼀个簇中占⽤了多少个字节,所以⽂件长度字段还是很有意义的。到对应的簇之后从对应的簇中读取数据即可,easy is'nt it?

本文发布于:2023-07-29 08:32:36,感谢您对本站的认可!

本文链接:https://patent.en369.cn/patent/4/196968.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   扇区   系统   磁盘
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图