NTFS是建立在综合索引的基本功能之上,综合索引包含了具有某一特征类型的多个分类项,并使用一种有效的存储机制以便于快速查找。
NTFS文件系统在MFT中有每个文件的记录,但是在查找的时候并不是直接从头到尾搜索文件记录,而是另外建立了一些信息来记录这些文件记录的位置和概况,这些信息叫做索引,主要是用来管理目录和文件。
NTFS文件系统的索引是使用B-树实现的。和FAT32文件系统的列表式目录相比,树的优点是快速查找,缺点是对树的修改极其复杂,比如创建一个文件,在MFT中建立好文件记录之后,就对索引操作,首先查找合适的位置,然后插入这个MFT记录的索引项,再根据树的特征对整个索引进行调整。但是为什么要使用B-树呢,我觉得是一般的操作都是查找文件,而创建、删除文件是极少数情况,所以总的来说,使用B-树管理目录比较有效。
当索引项较少的时候(一般在五项内),它们可以全部存储在目录的索引根属性中,称为小目录。这些项存放在90H属性当中。
当索引项较多时,MFT记录的根目录容不下那么项,所以在其他地方开辟空间存放索引项,这些空间叫索引缓冲区,这种情况下就是大目录了,索引根存在于A0H属性。A0H属性的Run List记录着索引缓冲区的起始位置及大小。索引项是按照文件名Unicode字符顺序进行排序,父索引会有指向子索引缓冲区的指针,所以根本不用担心找不到索引项。
图6-6 NTFS大目录索引结构
图6-6是一个大目录索引的结构。在根目录中,有9个文件,所以要存放在大目录中。查找文件就是按照箭头的方向查找,如果要查找cc.txt,先在根目录中和gg.txt比较,发现文件名比gg.txt小,往左边的索引缓冲区小,再和aa.txt比较,这是比aa.txt大,在aa.txt的末尾有一个子索引缓冲区,就会到这里查找,和bb.txt比较,这是也是小的,继续往右边走,和cc.txt相比,刚好相等,就找到了文件索引,这时就得到这个文件的MFT参考号,从而可以得到文件的全部信息。
最重要的一点是,每一个文件夹都有一颗B-树,同一级目录就存在同一颗B-树中,而不是整个分区只有一颗B-树。B-树的实质就是一条排序好的链,所以查找文件很快。
索引缓冲区的大小一般是一簇,即4KB,所以可以存储20-30个索引项,具体的有多少项是根据文件名而定。索引缓冲区由标准索引头和索引项组成,如图6-7所示;标准索引头的结构如表6-7所示;索引项结构如表6-8所示。每个索引缓冲区的结束都会有一个空索引以表示结束,一般以10H为大小。
图6-7 NTFS索引缓冲区结构
表6-7 NTFS标准索引头结构
偏移 | 长度 | 描述 |
0x00 | 4 | 头标志,总是“INDX” |
0x04 | 2 | 更新序列号的偏移 |
0x06 | 2 | 更新序列号与更新数组以字为单位的大小 |
0x08 | 8 | 日志文件序列号 |
0x10 | 8 | 本索引缓冲区的索引分配中的VCN |
0x18 | 4 | 索引项偏移 |
0x1C | 4 | 索引项大小 |
0x20 | 4 | 所以想分配大小 |
0x24 | 1 | 如果不是叶节点,置1 |
0x25 | 3 | 0填充 |
0x28 | 2 | 更新序列 |
0x2A | 2S-2 | 更新序列数组 |
表6-8 NTFS索引项的结构
偏移 | 长度 | 描述 | 偏移 | 长度 | 描述 |
0x00 | 8 | 文件MFT参考号 | 0x08 | 2 | 索引项大小 |
0x0A | 2 | 文件名属性体大小 | 0x0C | 2 | 索引标志 |
0x0E | 2 | 填充 | 0x10 | 8 | 父目录MFT文件参考号 |
0x18 | 8 | 文件创建时间 | 0x20 | 8 | 最后修改时间 |
0x28 | 8 | 文件记录最后修改时间 | 0x30 | 8 | 最后访问时间 |
0x38 | 8 | 文件分配大小 | 0x40 | 8 | 文件实际大小 |
0x48 | 8 | 文件标志 | 0x50 | 1 | 文件名长度(F) |
0x51 | 1 | 文件名命名空间 | 0x52 | 2F | 文件名 |
2F+0x52 | P | 填充 | P+2F+0x52 | 8 | 子节点索引缓冲区的VCN |
对文件进行操作,索引项会引起很大变化。当创建文件时,系统会寻找合适这个文件名索引项的位置,然后插入索引项,如果这个索引项后面有其他索引项,其他索引项则往后移动;如果实在没有位置了,就开辟一个新的索引缓冲区。当删除文件时,删除了这个文件索引项后,后面的索引项会往前移动。
6.7 解析NTFS B-树
B-树是非常复杂的,根据表面的数据改动,是不知道具体怎么实现的,但是可以知道大概是怎么工作的。使用一个例子来解析B-树可能更好理解。这个例子使用一个全新格式化的4GB大小U盘,系统格式为NTFS,在根目录下存放着五个文件和一个文件夹,文件夹内有名为“mubiao.JPG”文件,现在要查找的就是这个文件,如图6-8所示。
图6-8 新格式化U盘根目录
第一步:读取BPB,定位MFT。DBR在分区的第一个扇区,如图6-9 ,从30H开始8个字节为MFT偏移位置,值为40000H,即MFT从簇262144开始,因为每簇有8个扇区,就是偏移2097152扇区。
图6-9 NTFS的BPB
第二步:定位MFT记录。跳转到2097152扇区,这里就是MFT的开始,根目录在固定的5号文件记录,而每个记录占用2个簇,定位到2097162就是根目录文件记录了。如图6-10所示,这个记录就是整个分区根目录的入口,主要看90H属性和A0H属性,因为是大目录,所以90H属性没有任何索引项。接下来分析A0H属性,这个属性有一个Run List,说明有索引缓冲区,Run List的值为“11 01 2C”,解析得到:有1个索引缓冲区,起始簇号为44,大小为1个簇。
图6-10 MFT的$Root元文件记录
第三步:定位根目录。根据第二步得到根目录索引缓冲区起始于352扇区,跳转并读取簇,得到数据如图6-11 所示,找到目录索引项“a”,解析这个索引项,主要是得到目录的MFT参考号,值为28H,即40号文件记录就是记录目录“a”的。
图6-11 根目录索引项
第四步:定位目录并读取索引项。上一步得到了目录“a”的MFT文件参考号40,加上MFT的偏移,这个目录的偏移扇区为2097232,再读取这个文件记录,只关心90H和A0H属性,如图6-12 。因为这个目录只有一个文件,所以索引项就存储在90H属性中,90H中有一个索引项是要找的“mubiao.JPG”,这个文件的MFT文件参考号是29H。值得注意的是,90H属性最后也有一个空索引项,90H属性本质上就是一个小的索引缓冲区,当目录文件较小时存储索引项,提高查找速度。在这个MFT记录中发现有两个结束标志“FF FF FF FF”,系统只会认为第一个有效,到了这个标志就不会往后解析,后面的数据和结束标志是以前留下来。
图6-12 “a”目录文件记录
第五步:定位文件。得到了“mubiao.JPG”文件的MFT参考号后,就可以跳转到2097234扇区就是文件记录,文件查找也就结束了,如图6-13 所示。找到文件后最关心的就是文件内容了,而数据最重要的也是Run List,这里的值为“22 0E 03 70 0F”,解析得到:这个文件的数据起始于簇3952,大小为782个簇。
图6-13 “mubiao.JPG”文件记录
怎么还有啊!还有最后一篇哦~