NTFS体系结构

假定读者对NTFSNew Technology File System)已有基本的了解,不再赘述NTFS的特性。

Microsoft发明了NTFS文件系统,为了能出色的完成使命,NTFS在设计上及其精细和完整。本文详细讨论NTFS卷(volumes)的体系结构,和构成NTFS分区(partition)的关键数据结构,解释NTFS如何使用重要的文件系统结构来储存信息,有时会与FAT文件系统进行比较。

NTFS体系结构概览

FAT文件系统的大部分缺点都直接来自其简单又过时的设计,比如由于没有考虑可能的安全和可靠性属性,导致后来很难在FAT分区上添加这些功能。相反,NTFS采用了一种全新的体系结构,不仅能支持许多高级的属性和功能,还使用了一个简单而优美的方案允许更多属性加入其中。

这个优美的方案体现在NTFS分区是如何存储数据上。实质上,NTFS里的所有数据都是文件,甚至包括NTFS内部使用的分区管理数据,统计信息,和控制信息等。控制信息(control information)存储在一些特殊文件里,在NTFS分区格式化的时候创建,它们被称为“元数据文件(metadata files)”,包含了诸如用户文件列表、卷属性、簇分配信息之类的数据。唯一的例外就是“分区启动扇区(partition boot sector)”,它位于所有其他元数据文件之前,定义了NTFS分区最基本的一些操作,比如如何加载操作系统。

这个优美的方案还扩展到了文件内部的结构里。NTFS分区里每个文件都是一些属性(attributes)的集合,文件的数据(data)只是属性之一,其他的属性还有文件名和大小等。这种结构看起来很像是数据库——操作系统把文件看成是包含了众多属性的对象,然后以此为基础进行各种操作。于是NTFS给文件增加一些新属性,就是很容易的事情了。

在内部,NTFS把所有文件(包括元数据文件)的存储方式都采用簇系统(cluster system)——每个文件都分散到一个或多个簇里,每个簇包含了2的幂次个512字节的扇区。表面上这和FAT文件系统的存储方式一样,但是底层的实现却是有差别的。

NTFS卷启动扇区(Volume Boot Sector

当创建NTFS分区的时候,首先创建的是卷启动扇区。它在结构上与FAT文件系统里的类似,并且是NTFS下少数几个不存储在主文件列表(master file table)里的元数据之一。NTFS的卷启动扇区有时也叫做分区启动扇区(partition boot sector),卷启动记录(volume boot record),或其它类似的名字。

注意:虽然名字里有“扇区(sector)”,实际上卷启动扇区占用了16个磁盘扇区(8KB)。

NTFS的卷启动扇区起始于分区的一个扇区,包含2个主要结构:

l  BIOS参数块(BIOS Parameter Block):包含卷的基本信息,比如标识卷的格式是NTFS,卷标签和大小。除此之外,NTFS提供了一个扩展BIOS参数块,包含其它卷信息,例如重要元数据文件的位置。

l  卷启动代码(Volume Boot Code):在NTFS里,这块程序代码表示如何装载Windows NT2000操作系统。常见的过程是装载NTLDR,把控制权交给它,让它来装载操作系统的其他部分。

FAT文件系统的卷启动代码向来是病毒程序最亲睐的领地之一,因为修改这部分代码能使病毒优先于操作系统启动。Windows NT2000对此重新设计以保证安全性,使得卷启动代码里的病毒极难传播,因为操作系统一旦取得控制权,就会严格限制磁盘读写操作。(当然,病毒还是可能在Windows NT/ 2000系统里存在。)

NTFS系统(元数据)文件

前面已经说过,NTFS文件系统把所有的数据,无论用户的还是系统的,都存储成文件。所以有一部分文件对于NTFS是非常重要的,即元数据文件。元数据文件在NTFS卷格式化的时候自动产生,并组织在整个分区的前面。现在解释这些文件如何工作有些为时尚早,我们从它们在分区里的位置开始,首先是主文件列表(MFT Master File Table)。MFT实际上也是元数据文件,但是它描述了其他的元数据文件,甚至有的元数据文件整个就在MFT里面。MFT为每个文件或目录都保存一个记录(record),如果这个文件太小,那么整个文件就可能都存储在这个记录里。因为元数据文件在NTFS也是“文件”,所以它们在MFT里也有对应的记录。实际上,MFT的前16个记录就是为元数据文件保留的。

“怎么听起来这么麻烦?”是的,这个系统非常复杂,但是它在逻辑上是完整和一致的,而且运行得很好。下表列出了元数据文件的重要信息:

Metadata File Name

File Name

MFT Record #

Description

Master File Table (MFT)

$MFT

0

这个记录表示MFT自己。这有点像“先有鸡还是先有蛋”的问题:MFT里的一个记录怎么能包含MFT自己?答案是这个记录只包含了MFT的描述信息。这样NTFS就可以大胆的宣布那个优美的设计方案了,因为连MFT自己都有一个MFT记录!

Master File Table 2 (MFT2) or Master File Table Mirror

$MFTMirr

1

这是MFT里前16个记录的副本。这个记录的数据要么存储于整个分区的中间位置(Windows NT 3.5及以前)或者是最后位置(Windows NT 4.0及以后)。这个副本用于备份MFT里最重要的前几个记录,以防磁盘损坏。

Log File

$LogFile

2

卷的事务日志文件。

Volume Descriptor

$Volume

3

包含卷(分区)的关键信息,比如标签,NFTS版本,创建时间等。

Attribute Definition Table

$AttrDef

4

这个列表包含NTFS文件各种属性的名字和描述,但不包括属性的值。

Root Directory / Folder

"." (分隔符)

5

这是一个指向根目录的指针。

Cluster Allocation Bitmap

$Bitmap

6

包含一个位图,标志哪些簇空闲,哪些簇已使用。

Volume Boot Code

$Boot

7

这个记录包含了卷启动代码(或指向代码的指针),作为真正的卷启动代码的备份。

Bad Cluster File

$BadClus

8

这个列表包含所有标记为“已坏”的簇,防止文件系统继续使用它们。

Quota Table

$Quota

9

如果开启了磁盘配额服务,这个记录包含配额信息。只在NTFS 5.0及以后有效。

Upper Case Table

$UpCase

10

包含把文件名转换成Unicode16-bit)文件命名系统(file naming system)的信息,用于内部兼容。

注意:MFT里的1115号记录是为以后的元数据文件保留的。

这个元数据系统的优美性体现在,把内部信息存储在文件里,使系统的可扩展性大大增加了。这些文件也不用存储在磁盘上指定的位置,如果磁盘某些区域坏掉了,只需把它们移动到其他地方就可以了。

主文件列表(MFT

MFT存储NTFS卷上所有文件和目录的信息,是所有系统文件里最重要的成员。MFT本质上是一个数据库表,包含了各种文件的各种属性。它就像整个卷的“目录”或控制中心,所有的操作都从它开始。FAT里的文件分配表(file allocation table)与之有点类似,但是在功能上远远不及。

当在NTFS卷里创建一个文件时,首先在MFT里创建它的记录。MFT里每个记录的大小是一个有争议的话题:我所知道的是它等于簇的大小,并且最小1024字节,最大4096字节。但是,有些说法是它要么1024字节,要么2048字节。后面会详细介绍。

MFT使用记录存储文件或目录的信息,这些信息就是属性。由于记录的大小有限,MFT有几种方式来存储一个文件的属性:驻留(resident)属性存储在MFT记录里面,非驻留(non-resident)属性存储在其他的MFT记录里或者在外部范围(extents)里。

记住NTFS里文件的数据也是属性之一,没有任何特殊性。这样小文件就变得很有意思:如果一个文件的所有属性和值(包括数据)比一个MFT记录还小,那么“数据”属性就可以是驻留的——存储在MFT记录里。所以,这样的文件不需要任何额外的存储空间,于是也不需要访问多次磁盘来得到文件的数据。

大文件会复杂一些。如果一个文件有太多的附加属性——可以是系统定义的标准属性,也可以是用户定义的新属性——使得一个MFT记录不能容纳,那么有些属性会被移出MFT记录,并转化成非驻留属性。大文件的数据一般都是外部属性(external attributes),而非常大的文件可能会导致包含文件数据块的指针也成为外部数据!

当文件系统里的文件或目录越来越多,NTFS必须给MFT增加更多的记录。为了保持MFT在磁盘上的连续性以提高性能,NTFS在开始时会为MFT保留12.5%的磁盘空间,即所谓的“MFT区域(MFT Zone)”。虽然这是留给MFT的“不动产”,但实际上它是很灵活的。如果整个磁盘的其他空间都使用完了,MFT区域会毫不犹豫的顶替上。同样,如果MFT使用完了MFT区域里的空间,那么操作系统会自动在磁盘其他地方给MFT分配更多的空间。这样MFT就能任意伸展,直到整个卷空间被用完。但这样也使MFT可能变得零碎,导致性能下降,并且MFT是不能进行碎片整理的。

注意:MFT的前16个记录是保留给元数据文件的,普通文件不能使用。

NFTS的分区及其大小

NTFS分区和FAT分区有本质的区别,无论是在结构上还是功能上。但是,从外部看,它们都遵循基本的分区规则。PC启动程序处理NTFS分区的方式和处理FAT分区的方式是一致的,所以,类似于FAT分区,你可以有NTFS主分区和逻辑分区,而NTFS逻辑分区必然是NTFS扩展分区的一部分。

NTFS最初设计时就考虑了企业级的应用环境,所以它能支持非常大的分区。回想当初Windows NT发布时,FAT还只有FAT12FAT16——FAT32还未出现。FAT16最大的分区大小是2GB,使用32KB的簇;或4GB,使用非标准的64KB簇,可能导致其他Windows版本不兼容。考虑到商业应用的巨大存储量,和商用服务器可能使用RAID磁盘阵列,如此小的分区肯定是不行的,NTFS必须突破这个限制。

NTFS里,一个分区的最大字节数是264次方,即16EB。许多磁盘限制都源自于工程师的想法,比如“2GB应该足够了”。不过现在16EB的限制在短期内应该能够满足大众的要求。

但是我们也要小心这些巨大的数字。比如,FAT32声称能支持2TB的分区,但代价是极大的空间浪费和庞大的文件分配表(file allocation table)。NTFS是一个完全不同的文件系统,它在设计的时候硬盘的大小还在以几GB来衡量,而现在突然要处理上千万GB的卷,我们不得不进行仔细的考虑。下面的内容显示,巨大的卷确实会有一些限制。

Windows NT下,启动分区的大小有严格的限制。在安装的时候,Windows NT会预先创建一个FAT16分区。即使你明确指出把Windows NT安装到NTFS分区上,它也会这么做,然后把这个FAT16分区转化成NTFS分区。而Windows NTFAT16分区最大是4GB,所以你的启动分区也只能这么大。又或者你使用第三方工具,把这个分区进行扩展,你仍被一个限制束缚:Windows NT不能从大于7.88GB的分区上启动,无论这个分区是什么。这个限制与Windows NT最初的设计有关,那时还没有能访问巨大磁盘空间的Int 13H扩展指令。

由于有这些限制,许多NT系统都至少有2个分区——小些的作为操作系统启动分区,大些的存储用户数据。用户甚至发现这种组织方式非常好,因为它区分了操作系统文件和用户自己的文件。启动分区的最大限制在Windows 2000里被解除了,现在你能把整个磁盘划分到一个分区里面了。

注意:有些BIOS访问IDE/ATA硬盘的问题也会导致磁盘最大分区的限制,这与操作系统是没有关系的。因为访问大于7.88GBIDE/ATA硬盘也需要BIOS支持Int 13H扩展指令。

NTFS的簇及其大小

NTFSFAT有一个相同点是,它们都不单独操作磁盘的一个扇区(sector),而是把若干个扇区组织起来,称为簇(clusters)或分配单元(allocation units)。这样做的主要原因是性能:如果一个巨大磁盘的每个扇区都单独的存储不同数据,那么将需要花费巨大的空间跟踪哪些扇区里存储了哪些数据,同时造成严重的数据碎片。

虽然NTFSFAT都使用簇,但是它们的用法非常不同。巨大FAT文件系统分区的主要性能问题是文件分配表(file allocation tables)变得庞大,而且FAT在设计的时候根本没考虑巨大分区的环境。相反的是,NTFS被设计成可以很好的处理巨大分区里的庞大内部数据结构(比如MFT)。

NTFSFAT都是根据分区的大小选择一个默认的簇大小,但是选择的方法和值不同。下表显示了NTFS不同分区大小下的默认簇大小:

分区大小 (GiB)

每个簇的默认扇区数

默认簇大小 (kiB)

<= 0.5

1

0.5

> 0.5 to 1.0

2

1

> 1.0 to 2.0

4

2

> 2.0 to 4.0

8

4

> 4.0 to 8.0

16

8

> 8.0 to 16.0

32

16

> 16.0 to 32.0

64

32

> 32.0

128

64

也许读者注意到了下面染色的部分,因为NTFS根据不同的操作系统采用了不同的选择方式:

l  Windows NT 3.5及以前:这些版本里,NTFS使用整个表的选择方案,即如果你创建一个6GB的分区,那么簇大小就是16个扇区(8KB)。

l  Windows NT 3.51及以后:只有上表的前4个选项有效,簇最大也只能是4KB

这种差别的来源也许会让人惊讶:它与NTFS的内置“压缩”功能有关。簇大小在4KB以上的NTFS分区不支持压缩,而大部分用户非常青睐“压缩”特性,于是新的Windows操作系统不再选择后面的簇大小。而Windows NT 3.5及以前的版本根本不支持文件压缩,于是干脆使用整个表的选项。实际上,很难找到一个系统运行如此古老的系统,还使用大于4G的硬盘。

分区的簇大小对系统的性能影响很大。上面显示的只是默认的簇大小,可以通过格式化的时候用“/A”参数改变,比如“FORMAT D: /A:8192”将把D盘点簇大小设置为8KB。但是这样做时要非常小心,比如可能导致压缩功能失效,或者增加磁盘的闲散空间(slack)。闲散空间的产生原因是文件对齐到簇大小时导致的末尾空间浪费。簇越大,浪费的空间越多:在FAT文件系统里如此,在NTFS里也是如此。对于现在的磁盘大小,采用4KB的簇大小是一个很好的折中方案。

注意:最后还有一个问题对NTFS分区的簇大小有影响。Windows NT下,如果你把一个FAT分区转化成NTFS分区,将总是使用最小的簇大小:512字节。实际上,即使你把Windows NT安装到NTFS分区里,也会如此,因为Windows NT总是会预先创建FAT分区,然后再转化成NTFS分区!Windows 2000里没有这个问题。

你可能感兴趣的:(windows,File,table,存储,磁盘,Allocation)