FAT文件系统解析(阿甘译)

http://www.nondot.org/sabre/os/files/FileSystems/fatFilesystem.txt

原文作者: Inbar Raz
/

  FAT是一个链表结构,DOS利用这个链表来保持对硬盘上数据的物理位置的追踪,并且可以为储存新文件分配空间。
   处于目录入口点谝移地址1ah的一个字(word)是这个分配链结构中,第一个簇的簇号。如果你在FAT中定位这个单元,它指向链结构的尾部,或者下一个单元,等等。观察下面示例:

    图1
  这个图表显示了读取FAT的一些重要概念。其中:
 1>这个文件--MYFILE.TXT有10个簇的长度。第一个字节在簇08H处,最后一个字节在簇1bH处,这个链结构是:8,9,0a,0b,15,16,17,19,1a,1b。每个入口都指示了链结构的下一个入口,最后一个入口被赋予特殊的代码(ff)。
 2>簇18H被标识为坏簇,不能分配给任何链结构。
 3>簇6,7,0cH-14H,1cH-1fH是空闲的,并且能够被分配。
 4>另外有一个链结构开始于簇2,结束于簇5。

+------------+
|  FAT细节  |  FAT结构一般开始于DOS分区的第一个逻辑分区,(你可以使用INT 25H 并且 DX=1 +------------+ 来读取它)。唯一确保的方法是读取启动扇区(DX=0),检查偏移0eH。这样能够知道在FAT之前有多少启动扇区和保留扇区,将这个值(通常是1)赋给DX,然后通过中断INT 25H来读取FAT。

  有可能存在不止一份的FAT的拷贝。通常存在两份完全的FAT拷贝。如果存在两份或者更多,他们都会被放在连续的空间(第二份FAT紧接着第一份放置)。

  你可以通过下面的手段来帮助你确定FAT的信息:
 1>使用INT 25H来读取启动扇区,并检验其中的数据域。
 2>使用DOS系统功能调用 36H 或者1CH 来检验硬盘总扇区和簇数。
 3>使用DOS系统功能调用 44H(假如设备驱动支持Generic IOCTL) DOS3.2
 4>使用DOS系统功能调用 32H来获得所有有用的信息。(未公开发布)

   注意:一些非启动型磁盘的启动扇区(例如 一些网络块设备和一些非常老式的硬盘)没有包含任何有
用的东西。

+-------------+
| 12位/16位 | FAT表能够是12位或者16位的。12位入口对小于384K的媒体存储效率很高,(整个+-------------+ 入口的FAT表能够放置在单个512字节的磁盘扇区。对于更大的媒体,每个FAT表入口必须映射到一个更大的簇尺寸),由此,一个20M的硬盘将需要分配16个磁盘扇区单元,才能使用12位格式(换一种说法,1个一字节的文件将会整整占用8K大小的磁盘簇)。 16位FAT表入口被DOS 3.0引入,目的是为了更有效地管理AT的20M硬盘。尽管如此,软盘和10M硬盘继续使用12位格式。你能够判断FAT表是12位结构还是16位结构的:


 DOS 3.0 : 如果一个磁盘有超过4086(0ff6H)的簇,它将使用16位格式(4096是12位格式簇的最大值,大于0ff6H是保留簇)。
 DOS 3.2 : 如果一个磁盘有多于20740(5104H)的簇,它将使用16位格式(即:任何超过10M大小的磁盘都使用16位格式,所有其他的--包括大容量的RAM磁盘--都使用12位格式)。


  注意:一个很常见的误区是:是16位格式的FAT允许DOS工作在大于32M的磁盘上。实际上,限制因素是中断调用?INT 25H/26H (DOS通过它进行磁盘的输入输出) 不能访问簇号高于65535。一般地,簇大小为512字节(远小于1K),所以有32M的限制。

 在DOS 4.0中,INT 25H/26H支持一种允许访问簇号高于65535的技术,所以支持大于32M DOS分区。 这对FAT的实现并没有影响。使用16位的FAT入口和4扇区的簇,现在DOS支持分区的大小高达134M(是8扇区簇的两倍)。


+-----------------+
| 读FAT表     | 在读取一个FAT表入口的过程中(沿着FAT链结构)??首先将整个FAT表读入内存中, +-----------------+从目录 表中得到起始簇号,然后对12位的入口进行下面的操作:

 þ 将簇号乘以3     -------------|
 þ 将上面的结果除以2? -------------+-------(每个入口都是1.5(3/2)字节长)
 þ 在得到的地址处读取一个字(WORD).(作为与FAT表起始位置的偏移)
 þ 假设该簇号是偶数,用0FFFH来屏蔽这个值(保留低12位)
  假设该簇号是奇数,将其值右移4位(保留高12位)
 þ 得到的结果就是链结构中下一个簇的入口。


  注意:一个12位的入口能够跨越扇区的边界,因此必须小心处理一个扇区中FAT表的缓冲设计。

 16位的入口要简单一些---每个入口包含16位的偏移,这个偏移是链结构中下个入口相对于FAT表起始位置的偏移(0ffffH表示链结构结束)。

+--------------+
| FAT 表的内容| FAT表的第一个字节叫做媒体描述符(Media Descriptor)
+--------------+ 或者FAT表的ID字节。接下来的5个字节(12位的FAT表)或者7个字节(16位的FAT表)都是0FFH,FAT表的其余部分由一些12位或者16位的单元组成,每个单元代表磁盘上的一个簇。这些单元包含下面值当中的一个:


 þ (0)000H ................... 空闲簇
 þ (f)ff0H through (f)ff7H ... 保留簇
 þ (f)ff7H ................... 坏簇
 þ (f)ff8H through (f)fffH ... 链结构的结束簇
 þ (0)002H through (f)fefH ... 链结构中的下一个簇

 注意:上面值的高半个字节仅仅在16位的FAT表中使用,例如:一个坏簇在12位的FAT表中被标识为0FF7H,在16位的FAT表中被标识为0FFF7H。

+------------------------------------------------+
|         将一个簇号转换成扇区号             | 当你从目录接口中得到一个文件的起始簇号,你也许+------------------------------------------------+ 想定位存储文件(或者子目录)数据的物理扇区。
  一个物理磁盘(或者一个硬盘的DOS分区)被设计成下面的样子:

 þ 启动扇区和保留扇区
 þ 第一个FAT表
 þ 第二个FAT表 (可选的 -- 在RAM磁盘上不使用)
 þ 根目录
 þ 数据区 (所有的文件数据都定居在这里^_^, 包括文件和目录)

  这个设计的每个区段都是可变的。必须获得每个区段的大小,以便进行簇到扇区正确的转换。下面的公式提供了一个官方发布的方法,来根据簇号得到DOS 的逻辑扇区号:
  
  根目录扇区数   = 每扇区的字节数/ (根目录的入口数 * 32)
  FAT表的扇区数   =  FAT表数目 * ?每个FAT表的扇区数
   数据起始扇区号  = 保留扇区数 + FAT表的扇区数+ 根目录扇区数

 INT 25h/26h 扇区号 = 数据起始扇区号 + ((某个簇号-2) * 每个簇的扇区数)

 其中下面的变量:

  每扇区的字节数  每个FAT表的扇区数   FAT表数目 

  根目录的入口数  保留扇区数      每个簇的扇区数

   都是从启动扇区或者BPB结构(如果能够访问)。得到的扇区号可以被赋给DX,通过INT 25H/26H来直接访问DOS 磁盘。

   如果你是一个怕麻烦的人,你可以通过使用未公开发布的DOS系统功能调用(fn 32h--获得磁盘信息),省去计算的麻烦,这个功能调用已经预先将数据计算好了,包括文件数据起始扇区号(也就是上面提到的“数据起始扇区号”).

   作者友情提示:上面我所发现的信息用处最大的地方是在对目录的扫描上。例如:可以省略DOS 的文件查找功能,可以直接对目录扇区的直接读操作。在一个必须得到所有文件和目录的清单的程序中,直接地访问目录扇区将会比DOS 功能调用fns 4eH和4FH大约快两倍。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值