前一段学习arm碰到了fat32文件系统,大概看了一下整个程序的长度,三十几页的长度吓住了我……看到那么长的程序发麻啊,就放了一个星期。也可能是加上同时学习FPGA和调频无线电,导致自己总是静不下心钻研进去。想想还是要静下心来一样一样完成,不能遇到点坎坷就放下吧……于是乎,开始从网站上搜索各种关于fat32的资料……经过两天的时间终于大概明白了fat文件系统的大概结构。应为我也是刚刚学不可能很深入,就讲解一下自己遇见的一些问题以及解决办法。也给学习fat的同学一个参考。
我学习的是fat32所以就以fat32为模板。先介绍下fat32,我们平时都操作过计算机,我们建个文档很容易吧,复制篇电影也挺简单,可是在硬盘上这些文件又是怎样存储的呢?还有硬盘上的数据文件数目不会少吧,这些计算机怎么进行无误的管理,这就需要文件系统,现在大多数硬盘都采用ntfs文件系统,然而早期的电脑以及现在的大多数手机,u盘,MP3等很多带有存储功能的设备还是使用fat32(fat32不支持单个大于4g的文件,可寻址空间可以达到2T,具体这些怎么计算大家可以参阅具体文档)。可以说他是操作系统和数据存储的支撑。现在的嵌入式免不了对数据的存储吧,所以fat32还是相当重要的,不懂他想diy个数码相框,mp3,视频播放器那是不可能的……
fat文件系统大致可以分为5部分:主引导记录MBR、操作系统引导记录DBR、FAT表、文件目录项FDT。这些东西到底储存在哪里?有何作用?这也是我起初的迷惑所在。其实这些东西在sd卡(或T-F卡)格式化之后会计算机会在卡的起始存储区域建立这些表格,当然文件的有效管理也是就是依靠他们。接下来在我寻找MBR是遇到了一个大问题(其实是个小问题,弄了一天才解决):我把我的sd卡,u盘统统格式化为fat32格式然后用winhex(软件)来查看磁盘里面的原始数据(都是些数字),他们统统的没有MBR,把sd卡在别人电脑上格式化还是没有。我就开始使劲的百度……别人总结的有的sd卡上面就是没有MBR我就只能信之,后来偶然看到振南写的znfat书的有一张讲到winhex说打开磁盘有两种格式:一种逻辑的,一种物理的。而之前我一直用的是逻辑的……物理磁盘打开后我狂晕,我一天没解决的问题就是因为这个。而物理和逻辑到底有 多大区别,其实很简单就是逻辑磁盘他把MBR包括MBR后面的空白扇区给隐藏了。直接把DBR当做0扇区。MBR有还是没有决定于你格式化所用的软件……而找到他究竟有何用?如果你的只是用来存储数据的sd卡,没有分区(一般sd卡都没有分区),不是操作系统启动盘,可以说他基本没用,找到他就是为了找到接下来要说的DBR的位置。如何找就要看里面的具体数据代表的含义,网上大多数资料都有,这里就不细说了。DBR中包含了很多信息,通过它我们可以找到FAT表和FDT文件目录。这里只是讲一下他的大概,也不深入讨论了。FAT32文件系统的DBR后面也留有备用空间,可以很方便以后的os代码扩展,这个DBR很关键所以在备用空间内有备份,大多数是再往后六个扇区的位置,这点在sd卡数据丢失再恢复有很大作用。通过DBR找到FDT文件目录就可以进行文件的读取了。FDT中记录了根目录文件的首簇,通过它可以找到FAT表里的记录,然后通过FAT链表把文件正常的读取出来。
综上所述读取文件步骤就是:MBR->DBR->FDT文件目录->FAT表->文件。这只是一个大概的步骤,而要真正实现文件的读取还有很多的细节问题……下面看一段我编写的找到DBR所在扇区的程序(更确切的说是修改,程序我一直都是参考stm32不完全手册里的例程他的这一部分写的我实在是搞不懂觉得太繁琐,呵呵……可能是人家思想深奥自己理解不透,于是自己在他的程序的基础上把他那部分替换自己写的):
unsigned char FAT_Init(void)
{
bootsector710 *bs
= 0;
//DBR结构体指针
bpb710
*bpb = 0;
//BPB结构体指针,BPB包含于DBR中
partrecord
*pr
= 0;
//MBR结构体指针
DWORD rltsector;
//相对扇区数
if(SD_ReadSingleBlock(0,fat_buffer))return 1;
if(fat_buffer[0]==0xeb||fat_buffer[0]==0xe9)
{
bs=(bootsector710*)fat_buffer;
//得到DBR数据指针
rltsector=0;
}
else
//假设读回来的是MBR
{
pr=(partrecord *)((partsector*)fat_buffer)->psPart;
//得到DPT数据指针
rltsector=pr->prStartLBA;
//得到DBR所在扇区(在DPT中记录)
if(SD_ReadSingleBlock(rltsector,fat_buffer))return 2;
if(fat_buffer[0]==0xeb||fat_buffer[0]==0xe9)
{
bs=(bootsector710*)fat_buffer;
}
else return 3;
}
bpb = (bpb710 *)bs->bsBPB;
//最后的到的就是BPB所在地址
}
这段程序的具体思路就是先读取第一扇区的第一个字节,看是否是0xeb,是的话证明没有MBR即第一字节就是DBR,然后就可以直接定位到BPB所在地址(BPB就是DBR中存放重要参数的一部分)。
如果不是0xeb就假设它是mbr通过它找到DBR的地址偏移,读取DBR的第一字节,如果是0xeb则证明假设成立,开始就是MBR,同时也找到了DBR;假若不是0xeb证明这张sd卡的文件系统不是fat32,返回非零值,初始化失败。就先到这吧,刚看了没几天自己还不是很深入了解所以就只能总结下fat32的大体轮廓,如需完全掌握还要下深功夫…… |