有了之前读写block的基础之后,准备弄个文件系统,之前没有接触过这东西,所以有很多都晕晕的,但是看到fat的源代码之后还是挺有信心的,因为之前一直过uboot,所以这个文件当然是小巫见大巫了。首先来分析一下对应我的SD的FAT16的相关信息吧(暂且就这么称吧,因为我也不是很了解)。
一、引导扇区段
拿比较简单的FAT16文件系统来分析,格式化为FAT16,然后使用Winhex软件打开我的磁盘驱动器。先贴上一张图
这上面可以发现很多有用的信息,首先我们了解一下基本知识,对于我的SD卡来说,从上面的信息可以看出:
1、一个扇区定为512字节。
2、启动扇区为0扇区,同时这也是物理扇区0,但是,从上面可以看出,我的SD卡是没有MBR(主引导记录区)的,所以这个物理扇区0也就是我的DBR(系统引导扇区),也就是所谓的逻辑扇区0吧(这是我个人的理解)
补充一下:如果有MBR的,那么MBR为访问的第一个扇区,该扇区必须负责找到DBR
3、那么下面来分析一下这个DBR吧。看下面一张表,就可以知道它的定义了。下面这张表实在网上找的,所以和我的SD卡描述的不一样,我把我的SD描述的情况补充在后面。
自然从这个表上面我们可以获取如下主要信息:
每扇区字节数:0x0200 = 512字节
每簇扇区数: 0x20 = 32扇区
保留扇区数: 1扇区
FAT表份数: 0x02 = 2份
根目录项数: 0x0200 = 512,所以做多能存放的文件或者文件夹数目 = 512.
每个FAT表所占的扇区:0x00f3 = 243个扇区
FAT表所在的分区前面隐藏的扇区数:0x00 = 0,再次验证了我之前的猜测。没有MBR的,只有DBR。
卡的容量(总的扇区数): 0x1e5c00 = 1989632 ,那么换算成M就是: 1989632 * 512B = 971.5M
卡的ID: 0x980b5f1f
FilesysType :0x31544146就是FAT16的ASCII码。
可执行代码:从0x3c 开始的 347和字节都是可执行代码。
继续看表格。
DBR的偏移 0x5A开始的数据为引导代码。这是由偏移 0x00 开始的跳转指令所指向的。 所列出的偏移 0x00~0x02 的跳转指令"EB 3c 90"清楚地指明了引导代码的偏移位置。jump 3cH加上跳转指令所需的位移量,即开始于 0x3c。此段指令在不同的操作系统上和不同的引导方式上,其内容也是不同的。从头到尾梳理一遍,我们的FAT16文件系统框架就是这样:
引导扇区段
字节位移 字节长度 字段名称 0x00 3 跳转指令 0x03 8 OEM ID 0x0b 2 BPB 0x24 24 扩展BPB 0x3c 448 引导代码 0x1fe 4 扇区结束标识符
二、关于FAT表
1、FAT 表(File Allocation Table 文件分配表),是 Microsoft 在 FAT 文件系统中用于磁盘数据(文件)索引和定位引进的一种链式结构。假如把磁盘比作一本书,FAT 表可以认为相当于书中的目录,而文件就是各个章节的内容。但FAT 表的表示方法却与目录有很大的不同。 在 FAT 文件系统中,文件的存储依照 FAT 表制定的簇链式数据结构来进行。同时,FAT 文件系统将组织数据时使用的目录也抽象为文件,以简化对数据的管理。
2、FAT16 文件系统从根目录所占的 32 个扇区之后的第一个扇区开始以簇为单位进行数据的处理,这之前仍以扇区为单位。对于根目录之后的第一个簇,系统并不编号为第 0 簇或第 1 簇 (可能是留作关键字的原因吧),而是编号为第 2簇,也就是说数据区顺序上的第 1 个簇也是编号上的第 2 簇
3、FAT 文件系统之所以有 12,16,32 不同的版本之分,其根本在于 FAT 表用来记录任意一簇链接的二进制位数。以 FAT16 为例,每一簇在 FAT 表中占据 2字节(二进制 16 位)。所以,FAT16 最大可以表示的簇号为 0xFFFF(十进制的65535),以 32K 为簇的大小的话,FAT32 可以管理的最大磁盘空间为:32KB×65535=2048MB,这就是为什么FAT16 不支持超过 2GB 分区的原因。
FAT表记录了磁盘数据文件的存储链表,对于数据的读取而言是极其重要的,以至于Microsoft为其开发的FAT文件系统中的FAT表创建了一份备份,就是我们看到的FAT2。FAT2与FAT1的内容通常是即时同步的,也就是说如果通过正常的系统读写对FAT1 做了更改,那么FAT2 也同样被更新。如果从这个角度来看,系统 的这个功能在数据恢复时是个天灾
4、FAT 表实际上是一个数据表,以 2 个字节为单位,我们暂将这个单位称为FAT 记录项,通常情况其第 1、2 个记录项(前 4 个字节)用作介质描述。从第三个记录项开始记录除根目录外的其他文件及文件夹的簇链情况。根据簇的表现情况 FAT 用相应的取值来描述,特殊情况如下:
5、下面开始分析一个FAT表,我给SD装入一个文件,名为BingGe.bin
6、如上图,FAT表以"F8 FF FF FF" 开头,此2 字节为介质描述单元,并不参与FAT表簇链关系。可以看出是标识符和第一簇已被占用的意思。
它的第一个簇的地址是0x0002。这个地址从哪里得来的要看后面的内容了,暂且就把它当已知条件吧。这也就是说,在SD卡的第2个簇里边存放着dssd.bin的第1个16K数据,那么它的第二个16K放在哪里呢,我们要看FAT表,每2个簇对应于FAT表中的第4,5个字节,里边的内容为0003接下来的第4、5字节表示 0x0003,这是第2簇,
第6、7字节表示0x0004,这是第3簇
。。。
。。。
可以发现总共是到0x000b结束的。
所以可以推断出这个文件占用空间是9个簇,那么大小= (10*32*512) = 163840(簇注意结束符才算最后一个簇),那么我们截张图看一下,占用大小是多少
显然占用空间也是163840,完全和我们计算的一样。那么,我们继续跟踪一下,既然文件是按照簇为单位进行存储的,那么我们的一个簇是16KB,暂且不管第2个簇是什么内容。因为我们文件中的内容是从第2簇开始的,第2簇存放的是0003,数据0003表示接下来的簇是第3簇,以此类推,可以知道第9簇里面的内容是000b,接下来是第b簇也就是结束簇,至此完成FAT表的初步分析。
三、有关根目录
根目录区里面放的东西就是根目录下所见的东西,根据对引导扇区的分析,我们可以找到根目录区在第448扇区内,如何知道的呢?看一张图示表
红色箭头部分,表示保留扇区,这里我的SD卡是由两个保留扇区的。所以我们的根文件目录扇区 = (FAT*2)+保留+引导扇区 = 446+1+1 = 448扇区,从0开始,也就是第447扇区。那么我们的根文件目录就是第448扇区了。其实,当我们了解了整个结构之后,就能够通过winhex来,整体把握这个FAT的结构了。
1、开始贴上根目录里面的内容
FAT16和FAT32每个文件名都占32个字节,这里放的是短文件名。但FAT16的根目录区只有32个扇区,计算一下,每个扇区512字节,共32个扇区,而每个文件要占用32个字节,很显然,根目录只能放512个文件了。我们对照这下面的这个表格来提取信息
就看最前面的32字节吧,它表示了一个文件(或文件夹),现在对它分析一下。前11个字节是文件名。从后面的ASCII表中可以看出,它就是我写进去的那个名为BingGe.bin。至于为什么会出现那个A,我也不得而知了。 第0x0B个字节内容为0x20,可以知道它的属性为存档,这与我们从windows中观察到的它的属性是一致的。
0x18~0x19 中的日期=(年份-1980)*512+月份*32+日。得出的结果换
算成 16 进制填入即可。也就是:0x18 字节 0~4 位是日期数;0x18 字节 5~7 位
和 0x19 字节 0 位是月份;0x19 字节的 1~7 位为年号,原定义中 0~119 分别代
表 1980~2099,目前高版本的Windows允许取 0~127,即年号最大可以到 2107
年。
那么我看看我们的修改日期:3f 89 = 0011111 1100 01001,那么日期为9 ,月份为12月,年份为31+1980 = 2011年,所以修改日期应该为2011.12.9,再看看我们的文件
果然是没有错的。接着看目录是怎样访问的。
可以看到我们的一个文件夹地址是0x0c那么,跳转到这个簇去看一看就行了。
前面那个项,一个是2E,一个是2E 2E,它倒底是何方神圣,对照ASCII表,它就是一个小点“.”。这个小点什么意思,那第二项就是“..”,有没有什么启发?——DOS!那个
古老的操作系统是怎么访问文件夹的?cd ..就是返回上一层目录。难道是它……?没错!就是它,一个点代表当前目录,两个点代表上级目录。哈哈。看一下当前目录那一项,看一下它的地址,000A,就是这个目录。而..对应的那一项,分析一下地址。00 00,也就是根目录。所以就可以利用这里找到上一级目录,于是就可以实现一级一级目录的访问了。到这里根目录也就初步分析完毕了。接下来准备开始进行初步的移植文件系统了。