实现FAT文件系统,刚开始的时候对隐藏扇区和保留扇区很困惑,不清楚FAT表的入口地址应该根据什么来进行计算。查阅资料,对这个问题,网上并没有非常清晰的答案。这实际上是非常关键的一点,如果不清楚,那么无法获得BPB的信息。根据工作的进展,这个问题已经解决。现在读取128M/512M/1G的CF卡中的语音文件利用DAC播放,已经非常流畅了。下面对这个问题总结一下。
 
    假设现在有硬盘,或者CF卡,或者SD卡,就是存储介质, 我需要存放100个数据,那么如何存放呢?知道计算机中存放形式为二进制,也就是0/1。简单的把100个数据放到存储介质中可以,但是如果不同的数据多了,如何处理呢?这就引出了文件系统。文件系统实际上就是对存储的数据进行管理,这些存储的数据加上额外的管理开销,就形成了文件这个抽象的概念。而如何管理数据,如何降低开销,这些都是文件系统是否优越的重要指标。FAT文件系统采用的是链表的方式,一级一级的往下找。而在Linux下,ext2/3采用的是树的方式。在嵌入式系统中,不一定要有操作系统,也不一定要有文件系统,这些都需要根据具体的应用需求来进行系统设计。
 
    FAT(File Allocation TAble,文件分配表),我的理解是它是数据管理的额外开销部分,利用它,我可以知道文件的存放记录在那里,那么就可以找到文件记录;找到文件记录,就可以知道数据物理上在那里存放的,长度有多少,这样就可以把数据取出来。
 
    上面是些基本的知识,下面就隐藏扇区和保留扇区说一下我的理解。
 
    我在Windows XP SP2CF卡把格式化成FAT16文件系统,包括128M、512M、1G三种,利用Winhex工具查看具体信息。它们的参数如下:
 
128M:
    隐藏扇区 0
    保留扇区 6
    每簇4个扇区
    每个扇区512Bytes
512M:
    隐藏扇区 63
    保留扇区 4
    每簇16个扇区
    每个扇区512Bytes
1G:
    隐藏扇区 63
    保留扇区 6
    每簇32个扇区
    每个扇区512Bytes
 
    1 隐藏扇区(hidden sector)
 
    在分区之前的部分。通常所说的MBR,它是隐藏扇区的第一个扇区,也是整个存储介质的第一个扇区。使用C/H/S寻址方式为0 Cylinder / 0 Head / 1 Sector,换成LBA寻址方式,就是所谓的第0扇区。需要注意的是,隐藏扇区不是必须的,它是系统启动有关,如果你仅仅是作为存储,那么隐藏扇区可以没有,比如128M CF Card。还需要区分物理扇区和逻辑扇区。物理扇区是从整个存储介质的角度出发,而逻辑扇区仅仅是从该分区的角度出发。
 
    2 保留扇区(reserved sector)
 
    分区之内FAT表之前的所有扇区。通常所说的BPB,就是保留扇区的第一个扇区。如果隐藏扇区为0个,那么BPB所在的扇区就成为了实际的第0扇区。
 
| 隐藏扇区 | 保留扇区 | FAT表 | 根目录区 | 数据区 |
  分区前 <-|->分区之后,也就是文件系统的起始部分
 
    上面是FAT16的组织形式。默认上,LBA=0时,读取第一个扇区,得到的应该是MBR信息。在偏移位置为0x1be处,如果为0x80,则表示该分区是活动的。在偏移位置为0x1c6及其后的三个字节构成一个32位的长字(注意是按照小端存放方式),这是DBR的入口地址,也就是保留扇区的第一个扇区。如果在0x1be处不是0x80,则表明这不是MBR,也就是隐藏扇区为0,从保留扇区开始。那么读取LBA=0的扇区就是DBR了。
 
    由此看出相关的公式如下:
 
    1 读取LBA=0的扇区,如果判断是MBR,则说明存在隐藏扇区,根据MBR的信息找到分区的DBR扇区地址;
 
    2 读取DBR,分析相关的信息,获得文件系统参数BPB。
 
    FAT表的入口地址 = 隐藏扇区数 + 保留扇区数
    根目录区的入口地址 = FAT表的入口地址 + FAT的扇区数
    数据区的入口地址 = 根目录区的入口地址 + 根目录区的扇区数