zoukankan      html  css  js  c++  java
  • 详解FAT32文件系统

    详解FAT32文件系统

    硬盘是用来存储数据的,为了使用和管理方便,这些数据以文件的形式存储在硬盘上。任何操作系统都有自己的文件管理系统,不同的文件系统又有各自不同的逻辑组织方式。例如:常见的文件系统有FAT,NTFS,EXT,UFS,HFS+等等。下面就来学习一下基于Windows的FAT32文件系统。

    FAT32文件系统由DBR及其保留扇区,FAT1,FAT2和DATA四个部分组成,其机构如下图:

     

    这些结构是在分区被格式化时创建出来的,含义解释如下:

    DBR及其保留扇区:DBR的含义是DOS引导记录,也称为操作系统引导记录,在DBR之后往往会有一些保留扇区。

    FAT1:FAT的含义是文件分配表,FAT32一般有两份FAT,FAT1是第一份,也是主FAT。

    FAT2:FAT2是FAT32的第二份文件分配表,也是FAT1的备份。

    DATA:DATA也就是数据区,是FAT32文件系统的主要区域,其中包含目录区域。

    一、分析FAT32文件系统的DBR

       FAT32文件系统的DBR有5部分组成,分别为跳转指令,OEM代号,BPB,引导程序和结束标志。如下图是我U盘上一个完整的FAT32文件系统的DBR。

     

    E8 58 90 :(跳转指令) 本身占2字节它将程序执行流程跳转到引导程序处。

    “EB 58 90″清楚地指明了OS引导代码的偏移位置。jump 58H加上跳转指令所需的位移量,即开始于0x5A。

    4D 53 57 49 4E  34 2E 31 :(OEM代号) 这部分占8字节,其内容由创建该文件系统的OEM厂商具体安排。

    跳转指令之后是8字节长的OEM ID,它是一个字符串, OEM ID标识了格式化该分区的操作系统的名称和版本号。为了保留与MS-DOS的兼容性,通常Windows 2000格式化该盘是在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”。

    BPB:FAT32的BPB从DBR的第12个字节开始,占用79字节,记录了有关该文件系统的重要信息,各参数解释如下表:

    前面53个字节是BPB,后面26个字节是扩展BPB。

     

    对照上面分析:

    02 00:每扇区512字节

    40:每簇64个扇区

    26 B0:保留9904个扇区

    02:FAT数

    00 00:根目录项数为0

    00 00:小扇区数为0

    F8:硬盘

    00 00:每FAT扇区数为0

    00 3F:每磁道63个扇区

    00 80:128磁头

    00 00 1F 80:隐藏扇区8064

    03 A8 E4 00:总共61400064个扇区

    00 00 1D 48:每个FAT有7496个扇区

    00:扩展标志

    00 00:文件系统版本

    00 00 00 02:根目录簇号2

    00 01:文件系统信息扇区号

    00 08:备份引导扇区

    12个字节为0:保留

    00:软盘驱动器

    01:未知

    29:扩展引导标签

    78 7B 52 18:分区引导序号

    4B 49 4E 47 53 54 4F 4E 20 20 20:卷标KINGSTON

    46 41 54 33 32 20 20 20:系统ID  FAT32

    FAT32文件系统在DBR的保留扇区中安排了一个文件系统信息扇区,用以记录数据区中空闲簇的数量及下一个空闲簇的簇号,该扇区一般在分区的1号扇区,也就是紧跟着DBR后的一个扇区,其内容如下:

     

    52 52 61 41:扩展引导标签

    接下来的480个字节:未用

    72 72 41 61:文件系统信息签名

    00 02 07 9E:空闲簇数

    00 00 01 8F:下一个空闲簇的簇号

    接下来的14个字节:未用

    55 AA:结束标志

    引导程序代码:FAT32的DBR引导程序占用420字节,对于没有安装操作系统的分区来说这段程序是没有用处的。

    结束标志:DBR的结束标志与MBR,EBR的结束标志相同,为“55 AA”。

    二、分析FAT32文件系统的FAT表

    FAT32的组织形式来看FAT1在保留扇区(包括引导扇区)的后面,然后就是FAT2.

    所以我们在加上保留扇区的数量来到FAT1的第一个扇区:

    FAT文件系统之所以有12,16,32不同的版本之分,其根本在于FAT表用来记录任意一簇链接的二进制位数。以FAT16为例,每一簇在FAT表中占据2字节(二进制16位)。所以,FAT16最大可以表示的簇号为0xFFFF(十进制的65535),以32K(最多只支持64个扇区)为簇的大小的话,FAT16可以管理的最大磁盘空间为:32KB×65535=2048MB,这就是为什么FAT16不支持超过2GB分区的原因(DOS下)。

    FAT表结构及作用

    1、FAT32文件一般有两份FAT,他们由格式化程序在对分区进行格式化时创建,FAT1是主,FAT2是备份。

    2、FAT1跟在DBR之后,其具体地址由DBR的BPB参数中指定,FAT2跟在FAT1的后面。

    3、FAT表由FAT表项构成,我们把FAT表项简称FAT项,每个FAT项占用4字节。

    4、每个FAT项都有一个固定的编号,这个编号从0开始。

    5、FAT表项的前两个FAT项为文件系统保留使用,0号FAT为介质类型,1号FAT为文件系统错误标志。

    6、分区的数据区中每个簇都会映射到FAT表中的唯一一个FAT项,因为0号FAT和1号FAT被系统占用,用户的数据从2号FAT开始记录。

    7、如果某个文件占用很多个簇,则第一个FAT项记录下一个FAT项的编号(既簇号),如果这个文件结束了,则用“0F FF FF FF”表示。

    8、分区格式化后,用户文件以簇为单位存放在数据区中,一个文件至少占用一个簇。

    9、FAT的主要作用是标明分区存储的介质以及簇的使用情况。

    定位FAT绝对位置的方法如下:

    1、首先从MBR的分区表中得知分区的起始扇区,偏移到此扇区。

    2、从DBR的BPB中得知DBR的保留扇区数,FAT表的个数,FAT表的大小。

    3、因此FAT1=分区起始扇区+DBR保留扇区,FAT2=分区起始扇区+DBR保留扇区+FAT1。

    下图为FAT1的第一个扇区:

     

    上面是从第0项开始的,第0项和第1项暂时就不用看了,从第2项开始,为0F FF FF FF,表示这是一个小文件,只占用一个簇就结束了,然后第3、4项也是的。

    5簇中存放的数据是6,这又是一个文件或文件夹的首簇。其内容为第6簇,就是说接下来的簇位于第6簇——〉FAT表指引我们到达FAT表的第6簇指向,上面写的数据是7,就是说接下来的簇位于第7簇——〉FAT表指引我们到达FAT表的第7簇指向……直到根据FAT链读取到扇区相对偏移0×20~0×24,也就是第8簇,上面写的数据是9,也就是指向第9簇——〉第9簇的内容为”0F FF FF FF”,意即此文件已至尾簇。

    下面的同样的分析方法,我就不一一分析了。

    三、分析FAT32文件系统的数据区

    数据区的位置在FAT2的后面,具体定位方式如下;

    1、通过MBR中的分区表信息得知分区的起始位置。

    2、通过分区中DBR得知DBR的保留扇区数以及FAT表的大小,FAT表的个数。

    3、通过上面的信息就可以找到数据区的起始位置,数据区 = 隐藏扇区数+DBR保留扇区+(每个FAT表扇区数*2)。

    数据区的类容主要由三部分组成:根目录,子目录和文件内容。在数据区中是以“簇”为单位进行存储的,2号簇被分配给根目录使用。

    根据簇号得到在FAT中的扇区号和偏移:

    扇区号 = 簇号*4/每个扇区的字节数 + 隐藏扇区数 + 保留扇区数

    扇区偏移 = 簇号*4%每个扇区的字节数

    根据簇号得到起始扇区号:

    簇号起始扇区 = (簇号-2)* 每个簇的扇区数 + 隐藏扇区数 + 保留扇区数 + FAT数*每个FAT占扇区数

    下图为根目录的第一个扇区:

     

    FAT32文件系统中,分区根目录下的文件和目录都放在根目录区中,子目录中的文件和目录都放在子目录区中,并且每32个字节为一个目录项(FDT),每个目录项纪录着一个目录或文件(也可能是多个目录项记录一个文件或目录),如上图所示就是一个目录项。

    FAT32文件系统中,目录项可以分为四类:卷标目录项、“.”和“..”目录项、短文件名目录项、长文件名目录项。

    卷标目录项:卷标就是分区的名字,可以在格式化分区时创建,也可以随意修改,长度为11字节。

    “.”和“..”目录项:“.”表示当前目录,“..”表示上一层目录。这两个目录项多存在子目录中。

    短文件名目录项:所谓短文件名既文件名的“8.3”格式,此格式支持主文件名不能超过8字节,扩展名不能超过3字节。短文件名目录始终存放在一个目录项中。

    FDT第1字节又表明了该文件的状态,它有如下四种取值方式:
    a.   00H–目录项的空目录。
    b.   E5H–表示该目录项曾经使用过,但文件已被删除。
    c.   2EH–表示子目录下的两个特殊文件 “. “或 “.. “目录项
    d.   其它任何字符–表示一个文件名(或目录名)的第一个字符的ASCII码值.

    FAT第0xB个字节可以判别是长文件目录项还是短文件目录项。

    FAT32短文件目录项32个字节的表示定义如下:

     

    正如上面的第一个FDT就是一个短文件目录项:

    文件名为GAMES

    关于时间的表达方式:10111(23)   111000(56)   00001(1*2)时间值:23时56分02秒。

    关于日期的表达方式:0011101(29+1980)   1010(10)   10011(19)时间值:2009年10月19日。

    长文件名目录项:由于短文件名“8.3”的格式远远不能满足现实中的需求,所以就出现了长文件名。

    FAT32长文件目录项32个字节的表示定义如下:

     

    根据表中的长文件名组合方法我们可以得到上面根目录的第一个扇区中第7个FDT的长文件名为:urDrive

    如果是目录的话可以转到起始簇号在FAT1中的位置,然后转到相应的扇区分析FDT来枚举文件信息。

    详解NTFS文件系统

    上篇在详解FAT32文件系统介绍了FAT32文件系统存储数据的原理,这篇就来介绍下NTFS文件系统。NTFS、用过Windows系统的人都知道,它是一个很强大的文件系统,支持的功能很多,存储的原理也很复杂。目前绝大多数Windows用户都是使用NTFS文件系统,它主要以安全性和稳定性而闻名,下面是它的一些主要特点。

    安全性高:NTFS支持基于文件或目录的ACL,并且支持加密文件系统(EFS)。

    可恢复性:NTFS支持基于原子事务概念的文件恢复,比较符合服务器文件系统的要求。

    文件压缩:NTFS支持基于文件或目录的文件压缩,可以很方便的节省磁盘空间。

    磁盘配额:NTFS支持磁盘配额,可针对系统中每个用户分配磁盘资源。

    一、分析NTFS文件系统的结构

    当用户将硬盘的一个分区格式化为NTFS分区时,就建立了一个NTFS文件系统。NTFS文件系统同FAT32文件系统一样,也是用“簇”为存储单位,一个文件总是占用一个或多个簇。

    NTFS文件系统使用逻辑簇号(LCN)和虚拟簇号(VCN)对分区进行管理。

    逻辑簇号:既对分区内的第一个簇到最后一个簇进行编号,NTFS使用逻辑簇号对簇进行定位。

    虚拟簇号:既将文件所占用的簇从开头到尾进行编号的,虚拟簇号不要求在物理上是连续的。

    NTFS文件系统一共由16个“元文件”构成,它们是在分区格式化时写入到硬盘的隐藏文件(以”$”开头),也是NTFS文件系统的系统信息。

    NTFS的16个元文件介绍:

     

    首先找到该分区的起始扇区,具体可以参考 后面 MBR分区结构、DPT分区表、EBR扩展引导 这篇文章。

    二、分析$Boot文件

    $Boot元文件由分区的第一个扇区(既DBR)和后面的15个扇区(既NTLDR区域)组成,其中DBR由“跳转指令”、“OEM代号”、“BPB”、“引导程序”和“结束标志”组成,这里和FAT32文件系统的DBR一样。下图是一个NTFS文件系统完整的DBR。

     

    下面我们分析一下DBR中的各参数

    EB 58 90:(跳转指令)本身占2字节它将程序执行流程跳转到引导程序处。

    “EB 58 90″清楚地指明了OS引导代码的偏移位置。jump 52H加上跳转指令所需的位移量,即开始于0×55。

    4E 54 46 53 20 20 20 20:(OEM代号)这部分占8字节,其内容由创建该文件系统的OEM厂商具体安排。为“NTFS”。

    BPB:NTFS文件系统的BPB从DBR的第12个字节开始,占用73字节,记录了有关该文件系统的重要信息,下表中的内容包含了“跳转指令”、“OEM代号”以及“BPB”的参数。

     

    对照上面的BPB分析如下:

    02 00:每个扇区512个字节

    08:每个簇8个扇区

    00 00:保留扇区为0

    00 00 00:为0

    00:不使用

    F8:为硬盘

    00 00:为0

    00 3F:每磁道63个扇区

    00 FF:每柱面255个磁头

    00 00 00 3F:隐藏扇区数(MBR到DBR)

    00 00 00 00:不使用

    80 00 80 00:不使用

    00 00 00 00 0C 80 33 FF:扇区总数209728511

    00 00 00 00 00 00 00 03:$MFT的开始簇号

    00 00 00 00 00 85 57  80:$MFTmirr的开始簇号

    00 00 00 F6:每个MFT记录的簇数

    00 00 00 01:每索引的簇数

    B8 11 2A 0C B8 11 2A 0C:分区的逻辑序列号

    引导程序:DBR的引导程序占用426字节,其负责完成将系统文件NTLDR装入,对于没有安装系统的分区是无效的。

    结束标志:DBR的结束标志与MBR,EBR的结束标志相同,为“55 AA”。

    三、分析$MFT元文件

    NTFS文件系统中,磁盘上的所有数据都是以文件的形式存储,其中包括元文件。每个文件都有一个或多个文件记录,每个文件记录占用两个扇区,而$MFT元文件就是专门记录每个文件的文件记录。由于NTFS文件系统是通过$MFT来确定文件在磁盘上的位置以及文件的属性,所以$MFT是非常重要的,$MFT的起始位置在DBR中有描述。$MFT的文件记录在物理上是连续的,并且从0开始编号。$MFT的前16个文件记录总是元文件的,并且顺序是固定不变的。

    四、分析文件记录

    1、文件记录的结构

    文件记录由两部分构成,一部分是文件记录头,另一部分是属性列表,最后结尾是四个“FF”。如下是一个完整的文件记录:

     

    在同一系统中,文件记录头的长度和具体偏移位置的数据含义是不变的,而属性列表是可变的,其不同的属性有着不同的含义。后文将对属性进行具体分析,先来看看文件记录头的信息。

     

    NTFS文件系统中所有与文件相关的数据结构均被认为是属性,包括文件的内容。文件记录是一个与文件相对应的文件属性数据库,它记录了文件的所有属性。每个文件记录中都有多个属性,他们相对独立,有各自的类型和名称。每个属性都由两部分组成,既属性头和属性体。属性头的前四个字节为属性的类型。如下是以10H属性为例的属性结构。

     

    另外属性还有常驻与非常驻之分。当一个文件很小时,其所有属性体都可以存放在文件记录中,该属性就称为常驻属性。如果某个文件很大,1KB的文件记录无法记录所有属性时,则文件系统会在$MFT元文件之外的区域(也称数据流)存放该文件的其他文件记录属性,这些存放在非$MFT元文件内的记录就称为非常驻属性。

    分析属性的属性头

    每个属性都有一个属性头,这个属性头包含了一些该属性的重要信息,如属性类型,属性大小,名字(并非都有)及是否为常驻属性等。

    常驻属性的属性头分析表:

     

    如下是非常驻属性的属性头分析表:

     

    前面说过了,属性的种类有很多,因此各属性体的含义也不同。下表是NTFS文件系统中的所有属性体的简介。

     

    接下来来看几个重要的属性:

    分析10H属性:

    10H类型属性它包含文件的一些基本信息,如文件的传统属性,文件的创建时间和最后修改时间和日期,文件的硬链接数等等。如下:是一个10H类型的属性。

     

    其中偏移0×20处的文件属性解释如下:

     

    分析20H属性

    20H类型属性既属性列表,当一个文件需要好几个文件记录时,才会用到20H属性。20H属性记录了一个文件的下一个文件记录的位置。如下:是20H属性的解释。

     

    分析30H属性

       30H类型属,该属性用于存储文件名 ,它总是常驻属性。最少68字节,最大578字节,可容纳最大Unicode字符的文件名长度。

     

    分析80H属性

       80H属性是文件数据属性,该属性容纳着文件的内容,文件的大小一般指的就是未命名数据流的大小。该属性没有最大最小限制,最小情况是该属性为常驻属性。常驻属性就不做多的解释了,上面我标记的是一个非常驻的80H属性。

     

    其中,Run List是最难理解,也是最重要的。当属性不能存放完数据,系统就会在NTFS数据区域开辟一个空间存放,这个区域是以簇为单位的。Run List就是记录这个数据区域的起始簇号和大小,一个Run List例子上所示。这个示例中,Run List的值为“12 41 47 03”,因为后面是00H,所以知道已经是结尾。如何解析这个Run List呢? 第一个字节是压缩字节,高位和低位相加,1+2=3,表示这个Data Run信息占用三个字节,其中高位表示起始簇号占用多少个字节,低位表示大小占用的字节数。在这里,起始簇号占用1个字节,值为03,大小占用2个字节,值为47 41。解析后,得到这个数据流起始簇号为3,大小为18241簇。

     

    虽然数据不一样,但是表达的意思是一样的。

    分析90H属性

       90H属性是索引根属性,该属性是实现NTFS的B+树索引的根节点,它总是常驻属性。该属性的结构如下图:

     

    索引根的结构如表:

     

    索引头的结构如表:

     

    索引项结构如表:

     

    分析A0H属性

       A0属性是索引分配属性,也是一个索引的基本结构,存储着组成索引的B+树目录索引子节点的定位信息。它总是常驻属性。如下:是一个A0H属性的实例。

     

    根据上图A0H属性的“Run List”可以找到索引区域,偏移到索引区域所在的簇,如下图:

    起始簇:18265

    簇大小:3

    起始扇区号 = 该分区的其实扇区 + 簇号 * 每个簇的扇区数     也就是

    64 + 18265 * 8 = 146124

     

    对了,上面的偏移0×28还要加上0×18 = 0×40.

    标准索引头的解释如下:

     

    索引项的解释如下:

     

    到此一些常用属性基本介绍的差不多了。

    下面来说下遍历一个分区下面文件列表的思路:

    1、定位DBR,通过DBR可以得知“$MFT”的起始簇号及簇的大小。

    2、定位“$MFT”,找到“$MFT”后,在其中寻找根目录的文件记录,一般在5号文件记录。

    3、在90H属性中得到B+树索引的根节点文件信息,重点在A0属性上。通过属性中的“Run List”定位到其数据流。

    4、从“Run List”定位到起始簇后,再分析索引项可以得到文件名等信息。

    5、从索引项中可以获取“$MFT”的参考号,然后进入到“$MFT”找到对应的文件记录。

    6、然后再根据80H属性中的数据流就可以找到文件真正的数据了。

    MBR分区结构、DPT分区表、EBR扩展引导

    主引导记录(Master Boot Record,缩写:MBR),又叫做主引导扇区,是计算机开机后访问硬盘时所必须要读取的首个扇区,它在硬盘上的三维地址为(0柱面,0磁头,1扇区)。在深入讨论主引导扇区内部结构的时候,有时也将其开头的446字节内容特指为“主引导记录”(MBR),其后是4个16字节的“磁盘分区表”(DPT),以及2字节的结束标志(55AA)。因此,在使用“主引导记录”(MBR)这个术语的时候,需要根据具体情况判断其到底是指整个主引导扇区,还是主引导扇区的前446字节。如下:

     

    对应到我电脑第一个扇区:

     

    启动代码

    主引导记录最开头是第一阶段引导代码。其中的硬盘引导程序的主要作用是检查分区表是否正确并且在系统硬件完成自检以后将控制权交给硬盘上的引导程序(如GNU GRUB)。 它不依赖任何操作系统,而且启动代码也是可以改变的,从而能够实现多系统引导。

    硬盘分区表

    硬盘分区表占据主引导扇区的64个字节(偏移01BEH–偏移01FDH),可以对四个分区的信息进行描述,其中每个分区的信息占据16个字节。具体每个字节的定义可以参见硬盘分区结构信息

     

    主引导记录的结构可以知道,它仅仅包含一个64个字节的硬盘分区表。由于每个分区信息需要16个字节,所以对于采用MBR型分区结构的硬盘,最多只能识别4个主要分区(Primary partition)。所以对于一个采用此种分区结构的硬盘来说,想要得到4个以上的主要分区是不可能的。这里就需要引出扩展分区了。扩展分区也是主要分区的一种,但它与主分区的不同在于理论上可以划分为无数个逻辑分区。

    扩展分区中逻辑驱动器的引导记录是链式的。每一个逻辑分区都有一个和MBR结构类似的扩展引导记录(EBR),其分区表的第一项指向该逻辑分区本身的引导扇区,第二项指向下一个逻辑驱动器的EBR,分区表第三、第四项没有用到。

    Windows系统默认情况下,一般都是只划分一个主分区给系统,剩余的部分全部划入扩展分区。这里有下面几点需要注意:

    • MBR分区表中最多4个主分区或者3个主分区+1个扩展分区,也就是说扩展分区只能有一个,然后可以再细分为多个逻辑分区。
    • Linux系统中,硬盘分区命名为sda1-sda4或者hda1-hda4(其中a表示硬盘编号可能是a、b、c等等)。在MBR硬盘中,分区号1-4是主分区(或者扩展分区),逻辑分区号只能从5开始。
    • MBR分区表中,一个分区最大的容量为2T,且每个分区的起始柱面必须在这个disk的前2T内。你有一个3T的硬盘,根据要求你至少要把它划分为2个分区,且最后一个分区的起始扇区要位于硬盘的前2T空间内。如果硬盘太大则必须改用GPT。

    那么现在来对主引导扇区中的DPT来进行分析:

    80 01 01 00 07 FE FF FF 3F 00  00 00 00 34 80 0C

    80:表示该分区为活动分区

    01 01 00:开始磁头/开始扇区和开始柱面

    07 :文件系统标志位  07表示NTFS文件系统

    FE FF FF :结束磁头/结束扇区和结束柱面

    00 00 00 3F :分区起始的相对扇区号

    0C 80 34 00:分区总的扇区数

    后面三个表项的分析方法同上。

    每一分区的第1至第3字节是该分区起始地址。其中第1字节为起始磁头号(面号);第2字节的低6位为起始扇区号,高2位则为起始柱面号的高2 位;第3字节为起始柱面号的低8位。因此,分区的起始柱面号是用10位二进制数表示的,最大值为2^10 = 1024,因逻辑柱面号从0开始计,故柱面号的显示最大值为1023。同理,用6位二进制数表示的扇区号不会超过2^6 – 1 = 63;用8位二进制数表示的磁头号不会超过2^8 – 1 = 255。每一分区的第5至第7字节表示分区的终止地址,各字节的释义与第1至第3字节相同。这里我们假设一种极端的情况:如果让第5至第7字节的所有二进制位都取1,就获得了柱面号、磁头号和扇区号所能表示的最大值,从而得到最大绝对扇区号为:

      1024 × 256 × 63 = 16,515,072

      这个扇区之前的所有物理扇区所包含的字节数为:

      16,515,072 × 512Bytes ≈ 8.46GB。

    由此可知硬盘的容量设计为什么会有8.4GB这一档,分区表每一分区的第1至第3字节以及第5至第7字节的数据结构已经不能满足大于 8.46GB的大容量硬盘的需要。考虑到向下兼容的需要,业界并未对从DOS时代就如此定义的硬盘分区表提出更改意见,否则改动所牵涉的面太广,会造成硬件和软件发展上的一个断层,几乎无法被业界和用户所接受。硬盘厂商解决这一问题的方法是定义了新的INT 13服务扩展标准。新的INT 13服务扩展标准不再使用操作系统的寄存器传递硬盘的寻址参数,而使用存储在操作系统内存里的地址包。地址包里保存的是64位LBA地址,如果硬盘支持 LBA寻址,就把低28位直接传递给ATA接口,如果不支持,操作系统就先把LBA地址转换为CHS地址,再传递给ATA接口。通过这种方式,能实现在 ATA总线基础上CHS寻址的最大容量是136.9 GB,而LBA寻址的最大容量是137.4GB。新的硬盘传输规范ATA 133规范又把28位可用的寄存器空间提高到48位,从而支持更大的硬盘。

      分区表每一分区的第8至第11字节表示该分区的起始相对扇区数(即该扇区之前的绝对扇区个数),高位在右,低位在左;第12至第15字节表示该分区实际占用的扇区数,也是高位在右,低位在左;分区表这类数据结构的表达方式与机器中数据的实际存储方式在顺序上是一致的,即低位在前,高位在后。因此,在从16进制向十进制作数值转换时,需将字段中的16进制数以字节为单位翻转调位,用4个字节可以表示最大2^32个扇区,即2TB=2048GB。

    系统在分区时,各分区都不允许跨柱面,即均以柱面为单位,这就是通常所说的分区粒度。在未超过8.4GB的分区上,C/H/S的表示方法和扇区数的表示方法所表示的分区大小是一致的。超过8.4GB的/H/S/C一般填充为FEH/FFH/FFH,即C/H/S所能表示的最大值;有时候也会用柱面对 1024的模来填充。不过这几个字节是什么其实都无关紧要了。

    从上面可以看到我电脑的DPT只有一个主分区和一个扩展分区。

    主分区从63扇区开始,大小为209728512扇区。  约为100GB也就是我的C盘大小。

    扩展分区从209728575扇区开始,大小为415408770扇区。 约为198GB也就是我后面两个盘的大小。

    扩展分区中的每个逻辑驱动器都存在一个类似于MBR的扩展引导记录(Extended Boot Record,EBR)。

    扩展引导记录包括一个扩展分区表和扇区结束标志55AA。一个逻辑驱动器中的引导扇区一般位于相对扇区32或63。如果磁盘上没有扩展分区,那么就不会有扩展引导记录和逻辑驱动器。第一个逻辑驱动器的扩展分区表中的第一项指向它自身的引导扇区;第二项指向下一个逻辑驱动器的EBR,如果不存在进一步的逻辑驱动器,第二项就不会使用,而被记录成一系列零。如果有附加的逻辑驱动器,那么第二个逻辑驱动器的扩展分区表的第一项会指向它本身的引导扇区,第二个逻辑驱动器的扩展分区表的第二项指向下一个逻辑驱动器的EBR。扩展分区表的第三项和第四项永远都不会被使用。

    扩展分区表项中的相对扇区数是从扩展分区开始的扇区到该逻辑驱动器中第一个扇区的扇区数;占用的扇区数是指组成该逻辑驱动器的扇区数目。

    有时候在磁盘的末尾会有剩余空间,由于分区是以1柱面的容量为分区粒度的,那么如果磁盘总空间不是整数个柱面的话,不够一个柱面的剩下的空间就是剩余空间了,这部分空间并不参与分区,所以一般无法利用。

    我们来到扩展分区的EBR。

     

    扩展分区第一项:起始相对63扇区,大小为207640062扇区。 约为99G我D盘的大小。

    扩展分区第二项(指向下一个逻辑驱动器的EBR)起始相对207640125扇区,大小为207768645扇区。为我最后一个盘的大小。

    再来到这个指向的这个逻辑驱动器的EBR。

     

    只有一项:起始相对63扇区,大小为207768582扇区。约为99G我E盘的大小。

    当然末尾还有一些剩余空间。625142448-625137345       2M多的剩余空间。

     

    WinHex和我们分析出来的是一样的。

     

    所以也可以自己写个程序来分析。

    最后附上几个常见的分区类型。

     

    GDT(全局描述符表)和LDT(局部描述符表)

    每个程序都有自己的LDT,但是同一台计算机上的所有程序共享一个GDT。LDT描述局部于每个程序的段,包括其代码、数据、堆栈等。GDT描述系统段,包括操作系统本身。

    全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此积存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。

    段选择子(Selector)GDTR访问全局描述符表是通过“段选择子”(实模式下的段寄存器)来完成的。为了访问一个段,一个Pentium程序必须把这个段的选择子装入机器的6个段寄存器的某一个中。在运行过程中,CS寄存器保存代码段的选择子,DS寄存器保存数据段的选择子。每个选择子是一个16位数。

    选择子中的一位指出这个段是局部的还是全局的(它是在LDT中还是在GDT中),其他的13位索引是LDT或GDT的表项编号,表示所需要的段的描述符在描述符表的位置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符,然后用描述符表中的段基址加上逻辑地址(SEL:OFFSET)的OFFSET就可以转换成线性地址。因此,这些表的长度被限制在最多容纳8K个段描述符。

    段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。

    例如给出逻辑地址:21h:12345678h转换为线性地址
    a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;左后的01b代表特权级RPL=1
    b. OFFSET=12345678h若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h

    ③局部描述符表LDT(Local Descriptor Table)局部描述符表可以有若干张,每个任务可以有一张。我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。如图

      

    LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。LDTR记录局部描述符表的起始位置,与GDTR不同LDTR的内容是一个段选择子。由于LDT本身同样是一段内存,也是一个段,所以它也有个描述符描述它,这个描述符就存储在GDT中,对应这个表述符也会有一个选择子,LDTR装载的就是这样一个选择子。LDTR可以在程序中随时改变,通过使用lldt指令。如上图,如果装载的是Selector 2则LDTR指向的是表LDT2。举个例子:如果我们想在表LDT2中选择第三个描述符所描述的段的地址12345678h。
    1. 首先需要装载LDTR使它指向LDT2 使用指令lldt将Select2装载到LDTR
    2. 通过逻辑地址(SEL:OFFSET)访问时SEL的index=3代表选择第三个描述符;TI=1代表选择子是在LDT选择,此时LDTR指向的是LDT2,所以是在LDT2中选择,此时的SEL值为1Ch(二进制为11 1 00b)。OFFSET=12345678h。逻辑地址为1C:12345678h
    3. 由SEL选择出描述符,由描述符中的基址(Base)加上OFFSET可得到线性地址,例如基址是11111111h,则线性地址=11111111h+12345678h=23456789h
    4. 此时若再想访问LDT1中的第三个描述符,只要使用lldt指令将选择子Selector 1装入再执行2、3两步就可以了(因为此时LDTR又指向了LDT1)
    由于每个进程都有自己的一套程序段、数据段、堆栈段,有了局部描述符表则可以将每个进程的程序段、数据段、堆栈段封装在一起,只要改变LDTR就可以实现对不同进程的段进行访问。

    段描述符

     

    P,present位,1表示所描述的段存在(有效),为0表示所描述的段无效,使用该描述符会引起异常 
    DPL,Descriptor privilege,描述符特权级别,说明所描述段的特权级别 
    DT,描述符类型位,1说明当前描述符为存储段描述符,0为系统描述符或门描述符. 
    TYPE: 
    0:A(accessed)位,表明描述符是否已被访问;把选择子装入段寄存器时,该位被标记为1 
    3:E(EXECUTABLE?)位,0说明所描述段为数据段;1为可执行段(代码段) 
    当为数据段时, 
       位1为W位,说明该数据段是否可写(0只读,1可写) 
       位2为ED位,说明该段的扩展方向(0向高位扩展,1向低位扩展) 
    当为可执行段是, 
       位1为R位,说明该执行段是否可读(0只执行,1可读) 
       位2为C位,0说明该段不是一致码段(普通代码段),1为一致码段 
    G为粒度位,0说明LIMIT粒度为字节,1为4K字节. 
    D位: 
       1.在可执行段中,D为1,表示使用32位地址,32/8位操作数;为0表示使用16位地址,16/8位操作数 
       2.在由SS寻址的段描述符(堆栈段?)中,D为1表示隐含操作(如PUSH/POP)使用ESP为堆栈指针,
         为0使用SP(隐含操作:未明确定义段属性类型USE16/USE32?66H,67H?) 
       3.在向低扩展的存储段中,D为1,表示段的上限为4G;为0上限为64K
    存储段描述符的结构表示:

    分段管理可以把虚拟地址转换成线性地址,而分页管理可以进一步将线性地址转换成物理地址。当CR0中的PG位置1时,启动分页管理功能,为0时,这禁止启动分页管理功能,并且把线性地址作物理地址使用。

    虚拟地址转为线性地址:

    线性地址= 段基指 + 偏移地址

    32位线性地址转为物理地址:
    32位分为:
    页目录索引:占最高10位,指示页目录表中第几个页表描述符
    页表索引:占12位到21位,也是10位。指示这页表中第几个页描述符
    页描述符:线性地址的低12位为页内偏移量。

  • 相关阅读:
    怎样在过滤器中读取配置信息?
    怎样将直接数据库中Json字段,映射到Mybatis中的Map类型?
    spring/boot 打包,资源/配置/业务文件分离
    使用VS Code推送代码到GitHub
    Clion下jni配置
    curl post请求总是返回417错误
    ubuntu 12.10 apt-get 源
    如何让git小乌龟工具TortoiseGit记住你的账号密码
    FastCgi与Cgi
    Libevent核心原理
  • 原文地址:https://www.cnblogs.com/Chary/p/12981056.html
Copyright © 2011-2022 走看看