文件分配表(FAT)和目录结构
MS-DOS 和视窗 9x 共享相同的文件分配表和目录结构。在这篇文章中,让我来谈谈它们。
MS-DOS 把你的文件保存在磁盘上。但是,它们是怎么组织的呢?让我来解释给你听。
我们先来看看书本是怎样被保存的吧。通常,人们把信息保存在书本中。书本是一类媒体。它们可以保存文本和图形信息。每一本书有一个书名。书名一般是每本书各不相同的,于是我们就可以用书名来把一本书同其他书区分开来。一本书通常只由纸张构成。纸的数量是可以数出来的。每一本书在书架上占有一席之地。当有必要整理书本的时候,它们可以被搬动。
MS-DOS 的 FAT(文件分配表)文件系统也有点像管理书本一样的。以下是 FAT 文件系统特点的列表。
MS-DOS 的 FAT 文件系统有如下特点:
1. 每个文件占用一定数量的“簇”(也称为“分配单元”),就像每一本书由一定数量的页构成一样。每个簇在磁盘上是唯一的。它们可以被编号。在 MS-DOS 中,一个磁盘有一个固定的簇的大小,并且簇是在磁盘上连续定义的。
2. 书本不可以被分割,但一个文件可以被分割成几部分然后再被保存在磁盘上。为什么要这样做呢?因为在书架上移动书本是一件简单的事,但是在一个磁盘上把文件从一个地方移动到另一个地方需要很多时间。并且更重要的是,文件可以被修改,所以一个文件随时可能变长或者变短。如果文件是按顺序存储的,就要在一个文件被修改的时候用很多时间把其余的文件也在磁盘上搬来搬去。所以文件不应该像书本在书架上那样总是按顺序存储。为了可以让文件被分割存储,FAT(文件分配表)就被采用了。FAT 是用来保存磁盘上的文件链的。由于每个簇可以被编号,于是就可以容易地确定一个文件在磁盘上的位置。如果你学过编程的话,你可能知道有关链接表的知识。在 FAT 中的信息就像是链接表。指向头结点的指针是记录在目录中的,而后续的指针就保存在 FAT 中。每个 FAT 表项代表一个簇。为了区分被占用的簇和空闲的簇,簇号是从三开始的。值为零的 FAT 表项代表空闲的簇。另一方面,在 FAT 中的链应该有一个结尾标记。MS-DOS 分别使用 0xFFF、0xFFFF 及 0xFFFFFFFF 来表示 FAT12、FAT16 及 FAT32 的结尾标记。这些标记非常像编程时使用的 NULL(空指针)。MS-DOS 也保留了一些其他的标记,就是 0xFF7、0xFFF7 及 0xFFFFFFF7,分别用来表示 FAT12、FAT16 及 FAT32 中的“坏簇”(就是磁盘有损坏的地方)。FAT 中的坏簇标记用来避免写入磁盘的坏区。
3. 目录用来保存文件名。就像书本有它们的名字一样,文件也有它们的名字。它们是在目录中列出的。同时,文件的第一个簇号也在目录中列出。MS-DOS 中,在磁盘上有一个根目录。根目录可以容纳固定数目的表项,并且它在磁盘上的位置也是固定的。(从视窗 95 的 OSR 2 版开始,它的 FAT32 文件系统有一个可变大小的根目录。这个根目录像子目录一样也对应一个 FAT 中的链。)一个“目录项”记录着在目录中的有关一个文件或者子目录的基本信息。从 MS-DOS 2.0 开始,MS-DOS 支持树形结构的目录。为此,MS-DOS 使用了子目录。一个子目录在磁盘上像一个文件一样地被存储,但它含有和根目录类似的目录表项。当然这是一个不错的注意。在一个子目录中的表项的数目是不受限制的(同根目录比较的情况下;当然它受磁盘空间的限制),因为一个子目录可以像文件一样延展或者缩小。为了把空闲的表项从已被占用的表项中区分出来,MS-DOS 假定当一个表项以字节 0xE5 或者 0x00 开头时,这个表项是空闲的。
4. 一个磁盘(逻辑驱动器,一个卷)的规格(FAT 类型 [8/12/16/32;一个或者两个 FAT],兼容的 MS-DOS 版本,磁盘大小,簇大小,根目录大小,卷标,卷序列号,等等)都是存储在引导扇区的。通常,一个扇区是在磁盘上的一个连续的 512 字节块(它的实际大小取决于磁盘的类型)。引导扇区也包含了 MS-DOS 的引导程序。在使用 MS-DOS 的 FORMAT.COM 格式化一个常规磁盘的时候,两个 FAT,一个根目录和引导扇区会被创建。
以上就是一个有关 FAT 和 MS-DOS 目录结构的故事。在实际使用中,这里有一些段落讨论 MS-DOS 的实际磁盘分配。
软盘在当今已经广泛使用了。虽然在今天它们没有像过去那样用得频繁,它们仍然是通用的。我想现今的 MS-DOS 格式化过的 3.5 英寸高密度软盘的规格可以作为一个例子。这个例子是一个视窗千禧版(Windows Me)的启动盘。
1. 磁盘的一开始是引导扇区。如果你使用的是 MS-DOS 的话这种情况是肯定的(对于大多数操作系统来说都是肯定的)。在引导扇区中有一个程序用来引导操作系统。在引导扇区中这个程序由在主引导记录中的一个程序或者计算机的 BIOS 程序加载。
让我们来看看它包含了些什么内容:
2. 第二到第十扇区是第一个 FAT(FAT 1),第十一到第十九扇区是第二个 FAT(FAT 2)。让我们来看它们包含些什么:
在里面有一个个的表项。这个 FAT 的类型是 FAT12,也就是说,每个表项占用 12 比特。簇号是以小端方式记录的。也就是说,像在内存中的一个整数一样,数字 0x3E4D(举例来说)是以“4D 3E”方式存储的(如果你懂得 C 语言编程,你可以试试看这个:{int i = 0x3E4D; printf("%X %X", (int)*( ((char *)&i) + 0 ), (int)*( ((char *)&i) + 1 ));} )。在 FAT12 中,两个相邻的数字比如 0xA3D、0x897 在任意可以被 3 整除的偏移位置被存储为“3D 7A 89”。在上面那张图中,一开始的表项是“FF0,FFF,003,004,005,006,007,008,009,00A,00B,00C,00D,00E,00F,010,011,012,013,……”。一开始的两个表项是 MS-DOS 保留的,所以实际上的记录是从第三个记录开始的,并且第三个表项实际上代表第一个簇,尽管它的簇号是 3。
请看上图。FAT 2 拥有和 FAT 1 一样的信息。两个 FAT 用来提高磁盘操作的可靠性。
3. 扇区 20 到 33 都是根目录的扇区。一张 3.5 英寸高密度软盘的根目录可以保存 224 个表项。每一个表项占据 32 比特,所以根目录的大小是 14 个扇区。让我们看看它们包含一些什么东西:
3.5 英寸的文件系统到这里就讲完了。
重要说明:FAT32 的结构与 FAT12 及 FAT16 的结构很不相同。我至今还不很清楚。
视窗 9x 和视窗 NT 支持长文件名,并且它们在目录中的列表是这样的:
你可以看见每个有长文件名的文件是这样的:长文件名的表项在短文件名前面以反过来的先后顺序列出(虽然在这幅图片中看不到),并且长文件名是以 UNICODE 编码表示的。为了避免它们在老版本的 MS-DOS 中被显示出来,长文件名的表项有一个属性“L”,意思是“卷标”。表示属性的字节是表项中的第十二个字节。这个字节是如下定义的(例子中的是任意长文件名表项的属性字节):
0 0 0 0 1 1 1 1
N N A D L S H R
N —— 保留
A —— 存档,表示文件被改动过了。当一个文件被改动时,这个属性就会由 MS-DOS 自动设置。
D —— 目录,表示文件是一个子目录。
L —— 卷标,表示文件名是一个磁盘卷标。
S —— 系统,表示文件是一个系统文件(这个文件将不会在目录列表中出现并且它是很重要的)。
H —— 隐藏,表示文件不会在目录列表中出现。
R —— 只读,表示文件不可以被修改或者删除。
长文件名表项以反过来的先后顺序保存长文件名。第一个表项以一个大写字母开始(可能是 A、B、C……)。后面的表项每个都是以一个顺序号 0x01、0x02 等等开始。长文件名的第一个字节表示记录的条数。比如说,“A”意味着第一个表项是唯一的表项。“C”则表示包括第一个表项在内一共有三个表项;之后应该有两条记录分别以 0x02 和 0x01 开始。并非所有的字节都可以作为文件名。只有第 2、3、4、5、6、7、8、9、10、11、15、16、17、18、19、20、21、22、23、24、25、26、29、30、31、32 这些字节可以。之所以其他字节不可以使用是因为视窗 9x 被设计成和以前的 MS-DOS 版本兼容。第 27 和 28 字节用来保存 FAT16 文件系统下的起始簇号。在老 MS-DOS 中,如果这个表项是一个卷标,它们应该被设置成零。第 13 和 14 字节在老 MS-DOS 中是保留的,但它们在 FAT32 文件系统中有意义。长文件名的属性字节一定要是 0x0F。
准确信息请参考这个页面:视窗“长文件名”标准。
现在让我们来讨论一些 MS-DOS 中常见的操作。
“删除”操作。在 MS-DOS 中删除一个文件只用一个很短的时间。为什么呢?因为只有那个目录表项被标记为“空闲”以及 FAT 中的相关表项被标记为“空闲”。文件所占据的空间没有被清扫过。为了释放一个目录表项,MS-DOS 标记该表项的第一个字节为 0xE5。为了释放一些 FAT 中的表项,MS-DOS 把这些表项标记为 0x000、0x0000 或者 0x00000000(分别对应 FAT12、FAT16 和 FAT32)。所以一个被删除的文件有时候可以被恢复。但是注意:在老版本 MS-DOS 中的 UNDELETE 命令不可以在视窗 9x 或者视窗 NT 中使用,并且它也不可以用于 FAT32 驱动器。要恢复一个被删除的文件,你可以使用视窗 9x/视窗 NT 版诺顿实用工具中的 Norton UnErase(诺顿反删除),或者一些其他为视窗系统设计的工具。
“覆盖”操作。覆盖一个文件实际上意味着先把文件占据的簇重新重新写一遍,并且如果原来的文件没有足够多的簇的话 MS-DOS 会分配更多的簇。所以如果你想要把一个文件彻底删除,最好的办法是把文件用另一个文件(不能比原来的文件小)覆盖,然后再删除。你也可以使用一些工具比如诺顿实用工具—— Wipe Info(清除信息)来完成这个任务。
“移动”操作。在同一个磁盘上移动一个文件或者目录仅仅意味着把目录表项从一个目录移动到另一个目录。所以这个操作甚至比删除操作还要快。视窗系统中的“回收站”在删除一个文件的时候做了下列事情:它先把文件的信息收集起来(包括文件名、大小、删除时间和原来的位置),然后把它移动到所在磁盘上的“\RECYCLED”目录,同时把它的名字改为“DCxxx”(“C”表示 C 盘),其中“xxx”是一个数字,把它的信息保存在“\RECYCLED\INFO”文件(视窗 9x/NT)或者“\RECYCLED\INFO2”文件(视窗千禧版/2000)中。所以把一个含有很多文件的目录移动到回收站比把它移动到在同一个磁盘上的其他普通目录要慢。
返回 MS-DOS 基础知识