1、硬盘物理结构和 FAT 文件结构分析 一、硬盘的物理结构: 硬盘存储数据是根据电 、磁转换原理实现的。硬盘由一个或几个表面镀有磁性物质的金属或玻璃等物质盘片以及盘片两面所安装的磁头和相应的控制电路组成(图1),其中盘片和磁头密封在无尘的金属壳中。 硬 盘工作时,盘片以设计转速高速旋转,设置在盘片表面的磁头则在电路控制下径向移动到指定位置然后将数据存储或读取出来。当系统向硬盘写入数据时,磁头中 “写数据”电流产生磁场使盘片表面磁性物质状态发生改变,并在写电流磁场消失后仍能保持,这样数据就存储下来了;当系统从硬盘中读数据时,磁头经过盘片指 定区域,盘片表面磁场使磁头产生感应电流或线圈阻抗产生变化,
2、经相关电路处理后还原成数据。因此只要能将盘片表面处理得更平滑、磁头设计得更精密以及尽量 提高盘片旋转速度,就能造出容量更大、读写数据速度更快的硬盘。这是因为盘片表面处理越平、转速越快就能越使磁头离盘片表面越近,提高读、写灵敏度和速 度;磁头设计越小越精密就能使磁头在盘片上占用空间越小,使磁头在一张盘片上建立更多的磁道以存储更多的数据。 二、硬盘的逻辑结构 硬盘由很多盘片(platter)组成,每个盘片的每个面都有一个读写磁头。如果有 N 个盘片。就有 2N 个面,对应2N 个磁头(Heads),从 0、1、 2 开始编号。每个盘片被划分成若干个同心圆磁道(逻辑上的,是不可见的。)每个盘片的划分
3、规则通常是一样的。这样每个盘片的半径均为固定值R的同心圆再逻 辑上形成了一个以电机主轴为轴的柱面(Cylinders),从外至里编号为0、1、2每个盘片上的每个磁道又被划分为几十个扇区(Sector), 通常的容量是 512byte,并按照一定规则编号为 1、2、3形成 CylindersHeadsSector 个扇区。这三个参数即是硬盘的物理参 数。我们下面的很多实践需要深刻理解这三个参数的意义。 三、磁盘引导原理 3.1 MBR(master boot record)扇区 计算机在按下 power 键以后,开始执行主板 bios 程序。进行完一系列检测和配置以后。开始按 bios 中设定的
4、系统引导顺序引导系统。假定现在是硬 盘。Bios执行完自己的程序后如何把执行权交给硬盘呢。交给硬盘后又执行存储在哪里的程序呢。其实,称为MBR的一段代码起着举足轻重的作用。MBR (master boot record),即主引导记录,有时也称主引导扇区。位于整个硬盘的 0 柱面 0 磁头 1 扇区(可以看作是硬盘的第一个扇区),bios 在执行自己固有的程序以 后就会jump到mbr 中的第一条指令。将系统的控制权交由mbr来执行。在总共512byte的主引导记录中,MBR的引导程序占了其中的前446个字 节(偏移0H偏移1BDH),随后的64个字节(偏移1BEH偏移1FDH)为DPT(Di
5、sk PartitionTable,硬盘分区表),最后的两个字节“55 AA”(偏移1FEH偏移1FFH)是分区有效结束标志。 MBR 不随操作系统的不同而不同,意即不同的操作系统可能会存在相同的 MBR,即使不同,MBR 也不会夹带操作系统的性质。具有公共引导的特性。 我们来分析一段 MBR。下面是用 winhex 查 看 的 一 块 希 捷 120GB 硬 盘 的 MBR 。1你的硬盘的MBR引导代码可能并非这样。不过即使不同,所执行的功能大体是一样的。 我们看DPT部分。操作系统为了便于用户对磁盘的管理。加入了磁盘分区的概念。即将一块磁盘逻辑划分为几块。磁盘分区数目的多少只受限于 CZ
6、的英文字母 的数目,在上图 DPT 共 64 个字节中如何表示多个分区的属性呢?Microsoft通过链接的方法解决了这个问题。在DPT 共64个字节中,以16个字节 为分区表项单位描述一个分区的属性。也就是说,第一个分区表项描述一个分区的属性,一般为基本分区。第二个分区表项描述除基本分区外的其余空间,一般而 言,就是我们所说的扩展分区。这部分的大体说明见表1。 2注:上表中的超过1字节的数据都以实际数据显示,就是按高位到地位的方式显示。存储时是按低位到高位存储的。两者表现不同,请仔细看清楚。以后出现的表,图均同。 也可以在winhex中看到这些参数的意义: 3说明: 每个分区表项占用16个字
7、节,假定偏移地址从0开始。如图3的分区表项3。分区表项4同分区表项3。 1、0H 偏移为活动分区是否标志,只能选 00H 和 80H。80H 为活动,00H 为非活动。其余值对 microsoft 而言为非法值。 2、重新说明一下(这个非常重要):大于1个字节的数被以低字节在前的存储格式格式(little endian format)4或称反字节顺序保存下来。低字节在前的格式是一种保存数的方法,这样,最低位的字节最先出现在十六进制数符号中。例如,相对扇区数字段的值 0x3F000000 的低字节在前表示为 0x0000003F。这个低字节在前的格式数的十进制数为63。 3、系统在分区时,各分区
8、都不允许跨柱面,即均以柱面为单位,这就是通常所说的分区粒度。有时候我们分区是输入分区的大小为7000M,分出来却是 6997M,就是这个原因。 偏移2H和偏移6H的扇区和柱面参数中,扇区占6位(bit),柱面占 10 位(bit),以偏移 6H 为例,其低 6 位用作扇区数的二进制表示。其高两位做柱 面数 10 位中的高两位,偏移 7H 组成的 8 位做柱面数 10 位中的低 8 位。由此可知,实际上用这种方式表示的分区容量是有限的,柱面和磁头从 0 开始编号,扇区 从 1 开始编号,所以最多只能表示 1024 个 柱面63 个扇区256 个磁头512byte=8455716864byte。即
9、通常的8.4GB(实际上 应该是7.8GB左右)限制。实际上磁头数通常只用到255个(由汇编语言的寻址寄存器决定),即使把这3个字节按线性寻址,依然力不从心。 在后来的操作系统中,超过8.4GB 的分区其实已经不通过C/H/S的方式寻址了。而是通过偏移CH偏移FH共 4 个字节32位线性扇区地址来表示分区所 占用的扇区总数。可知通过4 个字节可以表示232个扇区,即2TB=2048GB,目前对于大多数计算机而言,这已经是个天文数字了。在未超过 8.4GB 的分区上,C/H/S 的表示方法和线性扇区的表示方法所表示的分区大小是一致的。也就是说,两种表示方法是协调的。即使不协调,也以线性寻址为 准
10、。(可能在某些系统中会提示出错)。超过 8.4GB的分区结束 C/H/S 一般填充为 FEH FFH FFH。即 C/H/S 所能表示的最大值。有时候也会用柱面对 1024 的模来填充。不过这几个字节是什么其实都无关紧要了。 虽然现在的系统均采用 线性寻址的方式来处理分区的大小。但不可跨柱面的原则依然没变。本分区的扇区总数加上与前一分区之间的保留扇区数目依然必须是柱面容 量的整数倍。(保留扇区中的第一个扇区就是存放分区表的MBR 或虚拟 MBR 的扇区,分区的扇区总数在线性表示方式上是不计入保留扇区的。如果是第一个分 区,保留扇区是本分区前的所有扇区。 附:分区表类型标志如图4 53.2 扩展
11、分区 扩展分区中的每个逻辑驱动器都存在一个类似于 MBR 的扩展引导记录( Extended Boot Record, EBR),也有人称之为虚拟mbr或扩展mbr,意思是一样的。扩展引导记录包括一个扩展分区表和该扇区的标签。扩展引导记录将记录只包含扩展分区中每个 逻辑驱动器的第一个柱面的第一面的信息。一个逻辑驱动器中的引导扇区一般位于相对扇区 32 或 63。但是,如果磁盘上没有扩展分区,那么就不会有扩展引导记 录和逻辑驱动器。第一个逻辑驱动器的扩展分区表中的第一项指向它自身的引导扇区。第二项指向下一个逻辑驱动器的EBR。如果不存在进一步的逻辑驱动器,第 二项就不会使用,而且被记录成一系列零
12、。如果有附加的逻辑驱动器,那么第二个逻辑驱动器的扩展分区表的第一项会指向它本身的引导扇区。第二个逻辑驱动器的 扩展分区表的第二项指向下一个逻辑驱动器的 EBR。扩展分区表的第三项和第四项永远都不会被使用。 通过一幅4分区的磁盘结构图可以看到磁盘的大致组织形式。如图5: 关于扩展分区,如图 6 所示,扩展分区中逻辑驱动器的扩展引导记录是一个连接表。该图显示了一个扩展分区上的三个逻辑驱动器,说明了前面的逻辑驱动器和最后一个逻辑驱动器之间在扩展分区表中的差异。 除了扩展分区上最后一个逻辑驱动器外,表2中所描述的扩展分区表的格式在每个逻辑驱动器中都是重复的:第一个项标识了逻辑驱动器本身的引导扇区,第二
13、个项 标识了下一个逻辑驱动器的 EBR。最后一个逻辑驱动器的扩展分区表只会列出它本身的分区项。最后一个扩展分区表的第二个项到第四个项被使用。 表2 扩展分区表项的内容 扩展分区表项 分区表项的内容 第一个项 包括数据的开始地址在内的与扩展分区中当前逻辑驱动器有关的信息 第二个项 有关扩展分区中的下一个逻辑驱动器的信息,包括包含下一个逻辑驱动器的EBR的扇区的地址。如果不存在进一步的逻辑驱动器的话,该字段不会被使用 第三个项 未用 6第四个项 未用 扩展分区表项中的相对 扇区数字段所显示的是从扩展分区开始到逻辑驱动器中第一个扇区的位移的字节数。总扇区数字段中的数是指组成该逻辑驱动器的扇区数目。总
14、扇区数字段的值等于从扩展分区表项所定义的引导扇区到逻辑驱动器末尾的扇区数。 有时候在磁盘的末尾会有剩余空间,剩余空间是什么呢?我们前面说到,分区是以1柱面的容量为分区粒度的,那么如果磁盘总空间不是整数个柱面的话,不够一个 柱面的剩下的空间就是剩余空间了,这部分空间并不参与分区,所以一般无法利用。照道理说,磁盘的物理模式决定了磁盘的总容量就应该是整数个柱面的容量,为 什么会有不够一个柱面的空间呢。在我的理解看来,本来现在的磁盘为了更大的利用空间,一般在物理上并不是按照外围的扇区大于里圈的扇区这种管理方式,只是 为了与操作系统兼容而抽象出来 CHS。可能其实际空间容量不一定正好为整数个柱面的容量吧
15、。 四、FAT 分区原理 先来一幅结构图: 图 7 现在我们着重研究 FAT 格式分区内数据是如何存储的。FAT 分区格式是 MICROSOFT 最早支持的分区格式,依据FAT表中每个簇链的所占位数(有关概念,后面会讲到)分为fat12、fat16、fat32三种格式“变种“,但其基本存储方式是相似的。 仔细研究图7 中的fat16和fat32分区的组成结构。下面依次解释DBR、FAT1、FAT2、根目录、数据区、剩余扇区的概念。提到的地址如无特别提示均为分区内部偏移。 74.1 关于DBR. DBR区(DOS BOOT RECORD)即操作系统引导记录区的意思,通常占用分区的第0扇区共512
16、个字节(特殊情况也要占用其它保留扇区,我们先说第 0 扇)。在这 512 个字节 中,其实又是由跳转指令,厂商标志和操作系统版本号,BPB(BIOS Parameter Block),扩展 BPB,os 引导程序,结束标志几部分组成。 以用的最多的 FAT32 为例说明分区DBR各字节的含义。见图8。 图8的对应解释见表3 表3 FAT32分区上DBR 中各部分的位置划分 表3 FAT32 分区上DBR中各部分的位置划分 字节位移 字段长度 字段名 对应图8颜色 0x00 3个字节 跳转指令 0x03 8个字节 厂商标志和os 版本号 0x0B 53个字节 BPB 0x40 26个字节 扩展B
17、PB 80x5A 420个字节 引导程序代码 0x01FE 2个字节 有效结束标志 图9给出了winhex对图8 DBR 的相关参数解释: 根据上边图例,我们来讨论DBR各字节的参数意义。 MBR将CPU 执行转移给引导扇区,因此,引导扇区的前三个字节必须是合法的可执行的基于x86 的CPU指令。这通常是一条跳转指令,该指令负责跳过接下来的几个不可执行的字节(BPB和扩展BPB),跳到操作系统引导代码部分。 跳转指令之后是 8 字节长的 OEM ID,它是一个字符串, OEM ID 标识了格式化该分区的操作系统的名称和版本号。为了保留与MS-DOS的兼容性,通常Windows 2000格式化该
18、盘是在FAT16和FAT32磁盘上的该字段中记录了“MSDOS 5.0”,在 NTFS 磁盘上(关于 ntfs,另述),Windows 2000 记录的是“NTFS”。通常在被 Windows 95 格式化的磁盘上OEM ID字段出现“MSWIN4.0”,在被Windows 95 OSR2和Windows 98格式化的磁盘上OEM ID字段出现“MSWIN4.1”。 接下来的从偏移 0x0B 开始的是一段描述能够使可执行引导代码找到相关参数的信息。通常称之为 BPB(BIOS Parameter Block),BPB一般开始于相同的位移量,因此,标准的参数都处于一个已知的位置。磁盘容量和几何结
19、构变量都被封在BPB之中。由于引导扇区的第一部 分是一个x86跳转指令。因此,将来通过在BPB末端附加新的信息,910可以对 BPB 进行扩展。只需要对该跳转指令作一个小的调整就可以适应 BPB 的变化。图 9 已经列出了项目的名称和取值,为了系统的研究,针对图8,将FAT32分区格式的 BPB含义和扩展BPB含义释义为表格,见表4和表5。 表4 FAT32分区的BPB字段 字节位移 字段长度(字节) 图 8 对应取值 名称和定义 0x0B 2 0x0200 扇区字节数(Bytes Per Sector) 硬件扇区的大小。本字段合法的十进制值有512、1024、2048和 4096。对大多数磁
20、盘来说,本字段的值为512 0x0D 1 0x08 每簇扇区数(Sectors Per Cluster),一簇中的扇区数。由于 FAT32 文件系统只能跟踪有限个簇(最多为4 294 967 296个),因此,通过增加每簇扇区数,可以使FAT32文件系统支持最大分区数。一个分区缺省的簇大小取决于该分区的大小。本字段的合法十进制值有 1、 2、4、8、16、32、64 和 128。Windows 2000 的 FAT32 实现只能创建最大为32GB的分区。但是,Windows 2000能够访问由其他操作系统(Windows 95、OSR2及其以后的版本)所创建的更大的分区 0x0e 2 0x00
21、20 保留扇区数(Reserved Sector) 第一个 FAT 开始之前的扇区数,包括引导扇区。本字段的十进制值一般为32 0x10 1 0x02 FAT数(Number of FAT) 该分区上FAT的副本数。本字段的值一般为2 0x11 2 0x0000 根目录项数(Root Entries)只有FAT12/FAT16使用此字段。对FAT32分区而言,本字段必须设置为 0 0x13 2 0x0000 小扇区数(Small Sector)(只有 FAT12/FAT16 使用此字段)对 FAT32 分区而言,本字段必须设置为0 0x15 1 0xF8 媒体描述符( Media Descri
22、ptor)提供有关媒体被使用的信息。值 0xF8 表示硬盘,0xF0表示高密度的3.5寸软盘。媒体描述符要用于MS-DOS FAT16磁盘,在Windows 2000中未被使用 0x16 2 0x0000 每 FAT 扇区数(Sectors Per FAT)只被 FAT12/FAT16 所使用,对 FAT32 分区而言,本字段必须设置为0 0x18 2 0x003F 每道扇区数(Sectors Per Track) 包含使用INT13h的磁盘的“每道扇区数”几何结构值。该分区被多个磁头的柱面分成了多个磁道 0x1A 2 0x00FF 磁头数(Number of Head) 本字段包含使用INT
23、 13h的磁盘的“磁头数”几何结构值。例如,在一张1.44MB 3.5英寸的软盘上,本字段的值为 2 0x1C 4 0x0000003F 隐藏扇区数(Hidden Sector) 该分区上引导扇区之前的扇区数。在引导序列计算到根目录的数据区的绝对位移的过程中使用了该值。本字段一般只对那些在中断 13h上可见的媒体有意义。在没有分区的媒体上它必须总是为0 0x20 4 0x007D043F 总扇区数(Large Sector) 本字段包含FAT32分区中总的扇区数 0x24 4 0x00001F32 每FAT扇区数(Sectors Per FAT)(只被FAT32使用)该分区每个FAT所占的扇区
24、数。计算机利用这个数和 FAT 数以及隐藏扇区数(本表中所描述的)来决定根目录从哪里开始。该计算机还可以从目录中的项数决定该分区的用户数据区从哪里开始 0x28 2 0x00 扩展标志(Extended Flag)(只被FAT32使用)该两个字节结构中各位的值为:位0-3:活动 FAT数(从0开始计数,而不是1). 只有在不使用镜像时才有效 位4-6:保留 位7:0值意味着在运行时FAT被映射到所有的FAT 1值表示只有一个FAT 是活动的 位8-15:保留 0x2A 2 0x0000 文件系统版本(File ystem Version)只供FAT32使用,高字节是主要的修订号,而低字节是次要
25、的修订号。本字段支持将来对该 FAT32 媒体类型进行扩展。如果本字段非零,以前的Windows版本将不支持这样的分区 0x2C 4 0x00000002 根目录簇号(Root Cluster Number)(只供 FAT32 使用) 根目录第一簇的簇号。本字段的值一般为2,但不总是如此 0x30 2 0x0001 文件系统信息扇区号(File System Information SectorNumber)(只供 FAT32 使用) FAT32分区的保留区中的文件系统信息(File System Information, FSINFO)结构的扇区号。其值一般为 1。在备份引导扇区(Backu
26、p Boot Sector)中保留了该 FSINFO结构的一个副本,但是这个副本不保持更新 110x34 2 0x0006 备份引导扇区(只供FAT32使用) 为一个非零值,这个非零值表示该分区保存引导扇区的副本的保留区中的扇区号。本字段的值一般为6,建议不要使用其他值 0x36 12 12个字节均为0x00 保留(只供FAT32使用)供以后扩充使用的保留空间。本字段的值总为0 表 5 FAT32分区的扩展BPB 字段 字节位移 字段长度(字节) 图8对应取值 字段名称和定义 0x40 1 0x80 物理驱动器号( Physical Drive Number) 与BIOS物理驱动器号有关。软盘
27、驱动器被标识为 0x00,物理硬盘被标识为 0x80,而与物理磁盘驱动器无关。一般地,在发出一个INT13h BIOS调用之前设置该值,具体指定所访问的设备。只有当该设备是一个引导设备时,这个值才有意义 0x41 1 0x00 保留(Reserved) FAT32分区总是将本字段的值设置为0 0x42 1 0x29 扩展引导标签(Extended Boot Signature) 本字段必须要有能被 Windows 2000 所识别的值0x28 或0x29 0x43 4 0x33391CFE 分区序号(Volume Serial Num ber) 在格式化磁盘时所 产生的一个随机序号,它有助于区
28、分磁盘 0x47 11 “NO NAME“ 卷标(Volume Label) 本字段 只能使用一次,它被用来保存卷标号。现在,卷标被作为一个特殊文件保存在根目录中 0x52 8 “FAT32“ 系统ID(System ID) FAT32文件系统中一般取为“FAT32“ DBR 的偏移 0x5A 开始的数据为操作系统引导代码。这是由偏移 0x00 开始的跳转指令所指向的。在图 8 所列出的偏移0x000x02的跳转指令“EB 58 90“清楚地指明了OS引导代码的偏移位置。jump 58H加上跳转指令所需的位移量,即开始于 0x5A。此段指令在不同的操作系统上和不同的引导方式上,其内容也是不同的
29、。大多数的资料上都说win98, 构建于fat基本分区上的win2000,winxp所使用的DBR只占用基本分区的第0扇区。他们提到,对于fat32,一般的 32 个基本分区保留扇区 只有第 0 扇区是有用的。实际上,以 FAT32 构建的操作系统如果是 win98,系统会使用基本分区的第 0 扇区和第 2 扇区存储 os 引导代码;以 FAT32 构 建的操作系统如果是 win2000 或 winxp,系统会使用基本分区的第0扇区和第0xC扇区(win2000或winxp,其第0xC的位置由第0扇区 的0xAB偏移指出)存储os引导代码。所以,在fat32分区格式上,如果DBR一扇区的内容正
30、确而缺少第2 扇区(win98系统)或第0xC扇区 (win2000或winxp系统),系统也是无法启动的。如果自己手动设置NTLDR双系统,必须知道这一点。 DBR扇区的最后两个字节一般存储值为0x55AA的DBR有效标志,对于其他的取值,系统将不会执行DBR相关指令。上面提到的其他几个参与os引导的扇区也需以0x55AA为合法结束标志。 FAT16 DBR: FAT32中 DBR的含义大致如此,对于FAT12和FAT16其基本意义类似,只是相关偏移量和参数意义有小的差异,FAT 格式的区别和来因,以后会说 到,此处不在多说 FAT12 与 FAT16。我将 FAT16 的扇区参数意义列表。
31、感兴趣的朋友自己研究一下,和FAT32大同小异的。 表6 一个FAT16分区上的引导扇区段 字节位移 字段长度(字节) 字段名称 0x00 3 跳转指令(Jump Instruction) 0x03 8 OEM ID 0x0B 25 BPB 0x24 26 扩展BPB 0x3E 448 引导程序代码(Bootstrap Code) 0x01FE 4 扇区结束标识符(0x55AA) 表 7 FAT16分区的 BPB字段 字节位移 字段长度(字节) 例值 名称和定义 0x0B 2 0x0200 扇区字节数(Bytes Per Sector) 硬件扇区的大小。本字段合法的十进制值有512、1024、
32、2048和 4096。对大多数磁盘来说,本字段的值为512 0x0D 1 0x40 每簇扇区数(Sectors Per Cluster) 一个簇中的扇区数。由于 FAT16 文件系统只能跟踪有限个簇(最多为 65536 个)。因此,通过增加每簇的扇区数可以支持最大分区数。分区的缺省的簇的大 小取决于该 分区的大小。本字段合法的十进制值有 1、2、4、8、16、32、64 和 128。导致簇大于 32KB(每扇区字节数*每簇扇区数)的值会引12起磁盘错误和软件错误 0x0e 2 0x0001 保留扇区数(Reserved Sector) 第一个 FAT 开始之前的扇区数,包括引导扇区。本字段的十
33、进制值一般为1 0x10 1 0x02 FAT数(Number of FAT)该分区上FAT的副本数。本字段的值一般为2 0x11 2 0x0200 根目录项数(Root Entries) 能够保存在该分区的根目录文件夹中的 32 个字节长的文件和文件夹名称项的总数。在一个典型的硬盘上,本字段的值为 512。其中一个项常常被用作卷标号 (Volume Label),长 名称的文件和文件夹每个文件使用多个项。文件和文件夹项的最大数一般为 511,但是如果使用的长文件名,往往都达不到这个数 0x13 2 0x0000 小扇区数(Small Sector) 该分区上的扇区数,表示为16位(=8GB
34、且=16GB 且=32GB 64 32k 20簇的取值意义和 FAT16 类似,不过是位数长了点罢了,比较见表 13: 表 13 FAT 各系统记录项的取值含义 (16 进制) FAT12 记录项的取值 FAT16 记录项的取值 FAT32 记录项的取值 对应簇的表现情况 000 0000 00000000 未分配的簇 002FFF 0002FFEF 00000002FFFFFFEF 已分配的簇 FF0FF6 FFF0FFF6 FFFFFFF0FFFFFFF6 系统保留 FF7 FFF7 FFFFFFF7 坏簇 FF8FFF FFF8FFFF FFFFFFF8FFFFFFFF 文件结束簇 FA
35、T32的另一项重大改革是根目录的文件化,即将根目录等同于普通的文件。这样根目录便没有了FAT16中512个目录项的限制,不够用的时候增加簇 链,分配空簇即可。而且,根目录的位置也不再硬性地固定了,可以存储在分区内可寻址的任意簇内,不过通常根目录是最早建立的(格式化就生成了)目录表。所 以,我们看到的情况基本上都是根目录首簇占簇区顺序上的第1个簇。在图4.3.12 中也是按这种情况制作的画的。 FAT32对簇的编号依然同FAT16。顺序上第1个簇仍然编号为第2簇,通常为根目录所用(这和FAT16是不同的,FAT16的根目录并不占簇区空间,32个扇区的根目录以后才是簇区第1 个簇) FAT32的文
36、件寻址方法与FAT16相同,但目录项的各字节参数意义却与FAT16有所不同,一方面它启用了FAT16中的目录项保留字段,同时又完全支持长文件名了。 对于短文件格式的目录项。其参数意义见表14: 表 14 FAT32 短文件目录项 32 个字节的表示定义 字节偏移 (16 进制) 字节数 定义 0x00x7 8 文件名 0x80xA 3 扩展名 00000000(读写) 00000001(只读) 00000010(隐藏) 00000100(系统) 00001000(卷标) 00010000(子目录 ) 0xB*1 属性字节 00100000(归档) 210xC 1 系统保留 0xD 1 创建时间
37、的 10 毫秒位 0xE0xF 2 文件创建时间 0x100x11 2 文件创建日期 0x120x13 2 文件最后访问日期 0x140x15 2 文件起始簇号的高 16 位 0x160x17 2 文件的最近修改时间 0x180x19 2 文件的最近修改日期 0x1A0x1B 2 文件起始簇号的低 16 位 0x1C0x1F 4 表示文件的长度 * 此字段在短文件目录项中不可取值0FH,如果设值为0FH,目录段为长文件名目录段 说明: (1)、这是FAT32短文件格式目录项的意义。其中文件名、扩展名、时间、日期的算法和FAT16 时相同的。 (2)、由于 FAT32 可寻址的簇号到了 32 位
38、二进制数。所以系统在记录文件(文件夹)开始簇地址的时候也需要 32位来记录,FAT32启用目录项偏移0x120x13来表示起始簇号的高16位。 (3)、文件长度依然用4 个字节表示,这说明FAT32依然只支持小于4GB的文件(目录),超过4GB的文件(目录),系统会截断处理。 FAT32 的一个重要的特点是完全支持长文件名。长文件名依然是记录在目录项中的。为了低版本的 OS 或程序能正确读取长文件名文件,系统自动为所有长文件 名文件创建了一个对应的短文件名,使对应数据既可以用长文件名寻址,也可以用短文件名寻址。不支持长文件名的 OS 或程序会忽略它认为不合法的长文件名字 段,而支持长文件名的O
39、S或程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。 当创建一个长文件名文件时,系统会自动加上对应的短文件名,其一般有的原则: (1)、取长文件名的前6 个字符加上“1“形成短文件名,扩展名不变。 (2)、如果已存在这个文件名,则符号“后的数字递增,直到5。 (3)、如果文件名中“后面的数字达到5,则短文件名只使用长文件名的前两个字母。通过数学操纵长文件名的剩余字母生成短文件名的后四个字母,然后加后缀“1“直到最后(如果有必要,或是其他数字以避免重复的文件名)。 (4)、如果存在老OS或程序无法读取的字符,换以“_“ 长文件名的实现有赖于目录项偏移为 0xB 的属性字节,当此字节的属
40、性为:只读、隐藏、系统、卷标,即其值为0FH时,DOS 和WIN32会认为其不合法而 忽略其存在。这正是长文件名存在的依据。将目录项的0xB置为0F,其他就任由系统定义了,Windows9x 或 Windows 2000、XP 通常支持不超过 255 个字符的长文件名。系统将长文件名以13个字符为单位进行切割,每一组占据一个目录项。所以可能一个文件需要多个目录 项,这时长文件名的各个目录项按倒序排列在目录表中,以防与其他文件名混淆。 长文件名中的字符采用 unicode 形式编码(一个巨大的进步哦),每个字符占据 2 字节的空间。其目录项定义如表15。 22表 15 FAT32 长文件目录项
41、32 个字节的表示定义 字节偏移 (16 进制 ) 字节数 定义 7 保留未用 6 1 表示长文件最后一个目录项 5 保留未用 4 3 2 1 0x0 1 属性字节位意义 0 顺序号数值 0x10xA 10 长文件名 unicode 码 0xB 1 长文件名目录项标志,取值 0FH 0xC 1 系统保留 0xD 1 校验值( 根据短文件名计算得出) 0xE0x19 12 长文件名 unicode 码 0x1A0x1B 2 文件起始簇号 (目前常置 0) 0x1C0x1F 4 长文件名 unicode 码 系统在存储长文件名时,总是先 按倒序填充长文件名目录项,然后紧跟其对应的短文件名。从表15
42、可以看出,长文件名中并不存储对应文件的文件开始簇、文件大小、各种时间和日期属性。文件 的这些属性还是存放在短文件名目录项中,一个长文件名总是和其相应的短文件名一一对应,短文件名没有了长文件名还可以读,但长文件名如果没有对应的短文件 名,不管什么系统都将忽略其存在。所以短文件名是至关重要的。在不支持长文件名的环境中对短文件名中的文件名和扩展名字段作更改(包括删除,因为删除是对 首字符改写E5H),都会使长文件名形同虚设。长文件名和短文件名之间的联系光靠他们之间的位置关系维系显然远远不够。其实,长文件名的0xD字节的校验 和起很重要的作用,此校验和是用短文件名的11个字符通过一种运算方式来得到的。系统根据相应的算法来确定相应的长文件名和短文件名是否匹配。这个算法不 太容易用公式说明,我们用一段c程序来加以说明。 假设文件名11个字符组成字符串shortname,校验和用chknum表示。得到过程如下: int i,j,chknum=0; for (i=11; i0; i-) chksum = (chksum