磁盘相关概念以及知识

http://code.riaos.com/?p=5011676

硬盘按照存储介质分为机械硬盘(HDD)和固硬盘(SSD)

硬盘的数据接口主要分为以下几种 :

ATA(IDE):从ATA1 到ATA7, 兼容性比较好,采用40pin并口数据线

SATA:ATA的继任者,串行的ATA接口,采用4pin的数据线,支持热插拔

SCSI:小型机系统接口,支持高转速的硬盘,传输时占用CPU资源较低,有50pin,68pin,80pin多种规格

SAS:串行 SCSI,是由SCSI演化过来的,比SCSI更快并且配置更简单。
兼容SATA设备,可以使用相同的电缆。SATA的硬盘可以接在SAS接口上使用

硬盘的电源接口

主要和数据总线有关,ATA接口的配备的电源接口为D形4针电源接口(大4pin接口),
而与SATA配合的则是5pin的L 型接口, 移动硬盘也可以通过USB接口供电。

硬盘的内部构造

磁头以及机械臂

由于有多张盘片,现代硬盘一般都有多个磁头,磁头也是硬盘中最贵的东西。
早期读写磁头是同一个,而新式的磁阻磁头(Magnetoresistive heads)将读写磁头分开
(感应写,磁阻读,通过阻值变化而不是电流变化去感应信号幅度),以达到更好的读写性能。

控制电机

令盘片高速转动起来,所有的盘片都固定在主轴上。盘片的转速甚至可以达到每分钟上万转。
硬盘的转速也是硬盘的一个重要参数。电器组件:包括一些控制电路以及硬盘的cache。

盘片

盘片一般是用用铝合金或者玻璃制成的,上面平铺一层磁性物质。为了节省空间,加大硬盘的容量,
盘片的正反两面都会被利用起来(但也有只用1面的)。逻辑上我们会从上到下给每个盘面一个编号,
从0开始。由于每一个盘面都会对应一个磁头,所以经常也会说0号磁头,1号磁头用来表示对应的盘面。

  • 磁道(TRACK):试想一下,电机开动,磁盘盘片开始狂转,将磁头固定好不动,磁头会划出一个圆形的轨迹,这个轨迹我们称之为磁道。
    有一点需要知道,磁道并不是紧挨着的。为啥?挨的太紧虽然可能增加盘片磁道的个数,但是会导致磁化单元间相互干扰影响,
    还有磁头读写定位也比较困难。磁道从外到内,依次从0开始编号,现代硬盘盘片上有成千上万的磁道。

  • 柱面(Cylinder):硬盘有多个盘面, 柱面实际上是多个相同半径的磁道集合。
    柱面也和磁道一样,由外圈向内,从0开始编号。
    0号柱面是指 0号盘面的0号磁道 + 1号盘面的0号磁道 + 2号盘面的0号磁道 。。。
    磁道是个平面的概念,柱面是个立体的概念。如果一个磁道写满了之后,接着写下一个盘面上的相同磁道
    记住这个规则,硬盘都是先写完一个柱面再接着写下一个柱面。

  • 物理扇区(Sector):为了和后面的逻辑扇区做区分,这里称之为物理扇区。扇区是磁盘读写的最小单位。
    所谓扇区,就是磁道上的一小段圆弧,扇区上存储着512字节的数据块。

    大家有没有思考过一个问题,在前面的那些描述中为什么每磁道的扇区个数都是一样的?

    按理说,外圈的圆弧长度大于内圈的,应该能存储更多的数据才对。最早的PC磁盘,每个磁道拥有17个扇区,
    由于技术的限制,内圈和外圈扇区个数相同,造成了外圈比较大的空间浪费。
    后来的 zone bit recording 技术解决了这个问题,可以令外圈的磁道拥有更多的扇区。
    而如今每个磁道可有有上千个扇区。换句话说,当今的磁盘, 每个磁道的扇区数是不一样的。(这句很重要)

    还有一点,扇区是从1开始,而不是0 (逻辑扇区是从0开始的,记住,我们这里说的是物理扇区!)
    关于为什么 不从0开始,我查了半天资料也没找出来,我个人猜想,
    0扇区会不会存放了一些磁道以及硬盘参数等信息,硬盘内部使用而不公开呢?

    关于扇区的组成,很多人会认为扇区的大小就是512字节,其实物理介质上存储的数据要比512大。 扇区大致由以下3部分组成:

    • 扇区头:一般含有扇区的地址信息(后面寻址会将到),扇区属于哪个柱面,哪个磁头以及扇区的序号。
      硬盘读取这个扇区数据时,首先比对一个扇区头的地址和想要读的地址是否相同。
      另外就是一个标志,如扇区是否不可用,或者有损坏(写入或者读取出错),
      还有sync标志(读取某扇区时,先要看此扇区是否已经写入完毕)以及
      重定向标志(标明这个扇区已经损坏,并给出另一个可用的扇区)。
    • 数据区:真正的数据。
    • 纠错码(ECC error-correcting code):ECC具体可以参看WIKI。
      硬盘读取扇区时,首先比对扇区头的地址信息,接着读取数据,计算出ECC,
      比对是否和此处的ECC码一致,不一致说明数据已经损坏。
      写的计算好ECC码,写入数据,接着将ECC写入扇区。

    根据上面的描述,大家应该知道,读写数据的有可能出现坏道(或者说扇区读写错误)有两种原因造成:

    • 逻辑坏道:读写数据与ECC码不一致。(解决方法试着再读写几次)
    • 物理坏道:扇区磁性介质物理损伤。 (无解。一些所谓的修复就是就是在扇区头加一个重定位标准,读写这个扇区时让磁头去读其他扇区)

    这些过程对于磁盘外部来说都是透明的,IDE控制器控制,关于扇区的确切的结构,这与不同的硬盘厂商相关,
    对于很多人来说,明白一个扇区是512字节就够了。(你这不是承认自己说了半天废话,
    看看我硬盘的ECC码的大小,50字节呀,也有ECC为40字节的)

    OK,完了。等下等下。。。既然扇区的结构各家厂商不太一致,那么,盘片造好的后,
    他们做了什么操作使磁盘扇区变成他们想要的结构? 对了,低级格式化,
    用低级格式化来划分磁道以及扇区结构(请参见本文后半部分).

    等等,前面说了那么多,

    扇区的大小为什么是512字节呢? 这有一些历史原因,一般物理扇区的大小为512字节,
    但也有一些不兼容IBM PC的硬盘设备扇区大小为520字节。现在也有1024字节,2048字节,以及4096(4K)字节一扇区的硬盘。
    2009年12月后,硬盘厂商开始发布4K扇区的硬盘,他们已经为这事酝酿十多年年了,4K扇区以后应该是主流。

    为什么会出现4K扇区的硬盘呢?由于人类太过贪婪,要求硬盘容量越来越大。硬盘厂商苦恼着不断想各种方法提升容量。
    从前面硬盘组成结构可知,提升容量可从下面三个方面入手:

    • 增加盘面的数量 => (亲,硬盘就那么厚,现在连正反面都用上了!)
    • 每个盘面划分更多的磁道 => ( 磁道已经密密麻麻的了,磁道再多的话,磁头就不好寻址了)
    • 提升磁性物质的密度,以及扇区间的空隙,划分出更多的扇区。 (现在又有垂直读写技术了!)

    我们来看第三点,存储密度越来越大,新的问题出现了!各个磁性物质间相互影响,造成磁头读取时的信噪比(SNR)不断下滑,
    换句话说,读一次,出现错误几率增大了。我们知道,ECC就是用来纠错的,每512字节的扇区,至少需要40字节的ECC码来进行纠错。
    如果。。。如果每4K的扇区,只需要100字节呀! 亲,赶紧算算: 512 * 8 = 4K => 40 * 8 = 320

    512的扇区4K需要320字节的ECC,而4K的扇区只需要100字节,一下子节省了220字节,好多呀!
    等等,还有更多的惊喜呢!扇区之间还有空隙,没有利用,使用4K扇区,这些空隙也可以被利用起来!
    请看下图的对比 !(图片可耻的copy自西数的某白皮书)

    再问一个问题,为毛是4K,而不是2K,8K? 4K,一个x86系统上神奇的数字。
    从文件系统层面上来说,磁盘的最小逻辑管理单位,簇 (NTFS)和块(EXT3) 都是以4K,刚好映射一个物理的扇区。
    而内存分页的大小也是4K,磁盘中一个扇区刚好能读进一个 内存分页中,非常完美。
    4K扇区,看起来很好,但同样也引入了一些麻烦。
    *首先产生了兼容性问题,因为BIOS,引导程序以及很多操作系统以及应用都认为硬盘物理扇区的大小为512字节,
    如果以4K为物理扇区,这些东西都要改,这也是为什么硬盘厂商酝酿了10年多才开始发布这种硬盘。
    目前为了解决这个问题,硬盘厂商采用了一种模拟的过渡方案,硬盘必须做一些额外的工作。
    以4K物理扇区为例,如果要修改512字节,硬盘需要先移动磁头到指定扇区,读取4K的数据到缓存中,
    修改4K中指定的512字节,然后再写回去。这种硬盘内部的转换过程称之为 “4K with 512-byte emulation”,简称512e。
    虽然解决了兼容性问题,但又产生了数据不一致以及性能等问题。随着4K扇区硬盘的推广,
    目前MS等操作系统厂商已经在操作系统层面开始解决这个问题,硬盘以4K作为读写颗粒,操作系统负责处理解决上层问题,
    并使操作系统的引导代码能直接使用4K扇区。(参看[这里](http://http://support.microsoft.com/kb/982018/zh-cn))

    * 再看另一个问题,即使上层以4K进行扇区操作,依然存在一个分区对齐的问题,未对齐的分区依然会对磁盘的性能产生重大影响。
    假设系统想要读取硬盘的上4K数据,而这4K前2K在一个扇区的后半部分,后2K在下一个扇区的前半部分。
    如果是读操作,影响不大,因为磁头几乎会连续通过这两个扇区,直接读2扇区,然后在缓存中丢弃掉没用的数据即可。
    但是对于写操作,就需要修改两个扇区,需要时间较多,造成应能下降。 所以说硬盘技术实际上一直在挖坑,
    512扇区一个大坑,CHS寻址一个坑,MBR又是一个坑,总是为了兼容折腾。
    (其实我觉得BIOS是个更大的坑,几十年来一直没啥变化,一些东西已经影响到了计算机的发展,MS等公司正 折腾着用EFI替换掉它)
    (下图展示了磁道扇区以及柱面的相关概念,copy自互联网)


硬盘的逻辑结构

逻辑扇区

是由系统划分的,大小为物理扇区的倍数,一般为512字节。等等,提问!为啥我还听过簇(cluster)和块(block)这两个概念呢?为啥没讲?

其实,簇就是一系列相邻逻辑扇区的集合,是微软系文件系统的概念,如FAT,FAT32,NTFS。
而块(block)是UNIX系文件系统的概念,和簇类似,一般是1024字节。这俩东西后面将具体 文件系统时再说。

硬盘的寻址

对于计算机来说,硬盘就是个黑盒,什么控制电机了,内部怎么旋转了,怎么定位了,都不想知道。
计算机只希望我给你电源接口供电,给数据接口发送指令,简化一下,大概分为2种操作:

  • 读操作:给数据接口发送读信号,并且给出想要读取数据块的位置以及大小。
  • 写操作:给数据接口发送写信号,给出想要写入的位置以及写入的数据,等待硬盘写入完毕。

好了,问题来了,这个位置如何表示?也就是硬盘的寻址问题.
根据寻址方式的不同,硬盘也出现了两种抽象。

  • CHS寻址: CHS寻址又叫3D寻址,比较好理解,对硬盘做简单的抽象,利用三个数字来定位数据。

    C (Cylinder)代表柱面号, H(Head)代表磁头号, S代表扇区号(Sector)。
    根据我们前面对磁盘结构的描述, 柱面从0开始,由外向内依次编号。
    磁头由上到下,从0开始依次编号。
    扇区从1开始编号。
    将硬盘想象成几个圆形盘片叠落在一起,H可以定位是那个盘片的那一面,
    C可以定位是磁道,S可以定位是哪一段圆弧。

    CHS三个数字即可完成寻址操作。

  • LBA寻址:LBA(Logical block addressing)是一种线性寻址方式,把硬盘想象成一种线性设备。
    LBA是比CHS更加高阶的一种抽象。大家可以将硬盘想象成一条很长很长的纸带或者干脆将硬盘当成一个巨大的文件,
    每512字节是一个逻辑扇区。LBA0 代表0扇区,LBA 8765代表第8765个扇区。
    LBA可以理解为是按扇区号进行编码的,磁盘的0柱面,0磁头,1扇区编号为0, 2扇区编号为1,以此类推。
    只需要一个LBA号即可完成定位。怎么样,相对于CHS更好理解,更简单吧?
    (注意: 在CHS寻址中扇区都是从1开始,而LBA有LBA0,也就是0扇区。)

硬盘的寻址的三种模式

在BIOS里硬盘寻址分为三种模式:CHS (NORMAL),LARGE 和LBA。

早期的ATA(IDE)接口的硬盘,是采用22bit的LBA进行寻址的,接着1994年,
ATA-1标准定义了2种 硬盘寻址方式,28bit的LBA 和 CHS。
CHS采用 16bit表示柱面序号, 4bit表示磁头序号, 8bit表示 扇区序号

IBM PC开始普及。IBM PC早期是使用软盘作为存储设备的,寻址方式是CHS,24bit。
10bit柱面, 8bit 磁头, 6bit扇区
IBM PC的BIOS中有个很著名的int 13中断(或者称之为 系统调用吧,可以想象成一个低级函数),
负责读取写入和校验磁盘。int 13中断就是按照 CHS 24bit这种方式来进行寻址的,而且实现还早于ATA-1标准。

当ATA接口的硬盘遭遇IBM PC的时候,问题就来了,不兼容,怎么办? 只能做映射了。
想一下, ATA的 28bit(16:4:8) 怎么映射成 (10:8:6) ? 最简单的方式就是将C 和 S的高位舍弃,将H的高位补0。
好了,问题解决。 等等,ATA的磁头当时定标准时为啥用4bit来表示,就不能多点吗?
亲呀, 当时的技术,4bit能表示16个磁头,相当于16个盘片放在一起,多厚呀(当时 还没双面的技术),
8bit 256个磁头你不觉得有点变态吗?

让我们想想现在又出现了什么问题,ATA的CHS 24bit(16:4:8)理论硬盘最大 支持到:

65536 * 16 * 255 * 512 = 127 GB

(注意:512指扇区大小为512字节, 255是由于扇区都是从1开始,而非0)

大约是127GB,我这里算的时候1M = 1024KB,和硬盘商的1M = 1000KB略微不同.

再看看IBM的CHS 24bit(10:8:6)的理论值: 1024 * 256 * 63 * 512 = 8GB(8064MB)

当ATA遇见IBM PC的时候,ATA限定了磁头最多为16个,所以真正的CHS 24bit 理论大小变成了:
1024 * 16 * 63 * 512 = 504MB

啊,就变成这么点了?我们称这个模式为Normal(或者None,或者CHS)模式,这个模式下,
最多访问504MB 的硬盘空间,C,H,S分别表示真正的物理柱面,磁头和扇区序号。

Normal模式下,有多于的柱面没有利用上,该怎么办呢? 对了,ATA的磁头太少了,我们虚拟一些磁头即可。
BIOS中引入了Large (或称为 Bit Shift Translation模式 ),当柱面多于1024的时候,
就进入Large模式,Large模式会对柱面和磁头做如下转换:

如果柱面大于1024,就除以2,并且对磁头数乘以2.

举个例子:2048柱面,6号磁头,1号扇区处的数据,直接拿来用(2048,6,1)在BIOS会认为是非法的
(因为柱面数大于1024)在large模式下会映射到 (1024,12, 1),合法!
多余的柱面映射完成! Large模式下寻址空间变成了IBM CHS 24bit的理论值 8GB。

在large模式中,我们已经虚拟了一些不存在的磁头,这里的CHS已经不完对应物理设备了。
(这也是 Normal模式称之为CHS寻址,而Large模式不那么称呼的原因了。)

插播一段小八卦,这里计算容量的时候,磁头最多有256个(0 – 255),由于MS 的DOS系统所有版本
都有一个bug,如果磁头有256个,就会引起系统crash….所以磁头一般序号最大为254, 实际可用的空间 再次减小,MS万岁!

8G貌似还不够,而且CHS模式目前遇见了问题,毕竟CHS也无法表述其他的存储设备,
如磁带,网络存储设备,SSD, 外加多块硬盘,磁头柱面之类的这些设备根本就不存在,于是引入

LBA寻址模式

ATA(IDE)控制器将LBA的地址转换成具体的物理地址。IDE标准可以使用22bit的LBA, ATA-1扩展到28bit, ATA-6再次扩展到48bit
2003年,ATA-6已经支持48bit的LBA寻址,硬盘最大支持到128PB,已经够大了。

实际上INT 13H Extensions支持64bit的LBA寻址,支持的硬盘大小已经达到目前的天文数字
(MBR最大支持2TB硬盘,所以也要被GPT替换了,后面我们详细再说吧,技术日新月异呀)。
不过现代的操作系统很多都不使用BIOS中的int 13中断了(除了在boot loader时),而是直接访问硬盘。

一般情况BIOS使用的是C/H/S(柱面,磁头,扇区) 寻址,由于硬盘容量增长太快了,由于分区表等
一些历史原因,C/H/S已经无法满足大分区的寻址了,现代操作系统都采用的是LBA寻址法。

大家明白我前面为啥说CHS又是一个坑了吧?

格式化

  • 低级格式化:如我前面所说,物理扇区是有一定格式组成的,每一块硬盘出厂前,需要进行“低级格式化”。
    所谓低级格式化,就是将硬盘划分出磁道,划分出物理扇区,使磁盘具有读写的能力。
    早期的硬盘,低格是一种物理操作,会影响硬盘的寿命,而现在的硬盘低格已经不再是物理操作,但建议还是不要乱进行低格。
    当你的硬盘的某些扇区因为一些原因丢失了扇区信息,可以尝试用低格来重新划分扇区。
    低格是针对整块硬盘的,重新划分磁道意味着原来的数据将要全部丢失,无法再恢复。
    如果你有块硬盘要送人又担心自己的隐私问题,建议对整块硬盘进行写0操作而非低格,
    因为据说低格很耗时间,320G的硬盘要20小时。。。(恐怖)

  • 高级格式化:高级格式化是针对某个分区进行了,按照你选定的文件系统格式(如FAT、NTFS 、EXT、HFS+),
    给特定区域写入特定信息,将分区按照文件系统定义的格式进行组织。

分区

分区就是将硬盘划分成几个逻辑部分,每一部分称之为一个分区。

为什么要有分区?,原因很多。一个熊孩子的电脑只有一个分区,格式化成一种文件系统,
结果有一天他说教练我还想再安装一个其他文件系统,怎么办?

分区的好处是可以在一个硬盘上安装多个文件系统。

  • 每个分区存放不同种类的数据,方便逻辑上管理。
  • 一个分区如果损坏,不会影响其他分区。
  • 操作系统一般都需要安装在独立分区内,多个分区可以安装多个操作系统。
  • 。。。。。

分区的类型:
分区分为主分区,扩展分区和逻辑分区。 怕大家搞混,我们慢慢来说。
硬盘的0柱面,0磁头,1扇区称之为主引导扇区(MBR),系统启动后,首先读取的就是这个扇区,
关于MBR的详细内容,后面有篇幅描述,大家现在只要知道,MBR中含有一个分区表,记录着硬盘上的分区。
由于一些历史原因,分区表中的分区最多只能有4个。换句话说,一块硬盘最多能分4个分区。

好像有点少呀,贪婪的人类不满足了,想要更多的分区,最简单的方法就是扩大MBR的分区表!
不行,MBR也是一个坑, 更改了MBR的格式,会引起很多兼容性问题。所以人们在不改变MBR结构的前提下,
把分区表中的最后一个分区加以特殊化,从而扩展出更多的分区。

分区表中的分区我们称之为主分区,主分区中那个特殊的分区,我们称之为扩展分区
主分区最多有4个,扩展分区最多有一个。

对于一个磁盘,我们可以这么分:

  • 1个或 2 个或 3个或4个主分区。 <= 不要扩展分区
  • 1个扩展分区 <= 不要主分区 (没有主分区的硬盘只能当数据盘,是无法引导操作系统的)
  • 1个或2个或3个主分区 外加一个扩展分区

那么逻辑分区又是什么东西呢? 刚才我们说了,分区表中有个特殊的分区,称之为扩展分区,
我们可以把扩展分区当成一个容器,再划分成N个分区,这些分区,对于MBR来说,不存在,
但对于我们来说,是存在的,这就是逻辑分区

简单的理解就是:

硬盘 = 主分区(最多有4个,可以不存在) + 扩展分区(最多有1个,可以不存在) + 未分配的空间(可以不存在)

扩展分区 = 逻辑分区1 + 逻辑分区2 。。。。。

关于主分区、扩展分区和逻辑分区我们就先说这么多,具体的结构在MBR和GPT部分详细解释。
下图展示了 包含2个主分区以及1个扩展分区还有3个逻辑分区的硬盘布局图:

(空白部分代表间隙。 另外,MBR只占512字节,没有图中画的那么大。。。)

MBR

MBR前面已经提过几次了(三个坑之一),到底是什么东西?

MBR,全称 Master Boot Record,中文一般翻译为主引导扇区(或者主引导记录),
MBR位于CHS 0/0/1处,也就是0号柱面0号磁头的第一个扇区。
MBR是硬盘中首先会被读入到内存中的部分,包含了引导代码以及分区表,非常非常重要。
MBR与具体的操作系统没有关系,可以和BIOS配合可以引导硬盘上操作系统。
MBR要是损坏了,只能通过探测式试探来修复。不过MBR存在一些限制,如最大支持2TB的硬盘,
主分区不能超过4个,再加上合它一起合作的是30多年也没什么变化的BIOS,
MS等厂商早对其不爽,吵着闹着要用GPT+ EFI 来替换掉它们(下节描述GPT)。

我们先来看看MBR的结构:

  • 446字节的引导代码
  • 64字节的分区表(包含4个项目,每项16字节)
  • 2字节的结束标志(55 AA)

总计512字节,刚好一个扇区。注意:MBR中的数据都是以小尾(Little-Endian)格式存放的。

虚拟出来的Disk 2的mbr 这是典型的MBR,不过现在的MBR 会在 446字节的引导代码中动一点手脚,
有的是218自己的引导代码,外加一些时间信息,还有的将扩展分区表写在了这里,
不管怎么样,64字节分区表的偏移没有改变。

在详细研究MBR之前,我们先简单看看BIOS + MBR系统开机的启动过程:

  1. 主板加电,从ROM中读取BIOS代码到内存中,并运行BIOS程序,将控制权交给BIOS。

  2. BIOS执行内存FFFF:0000H处的跳转指令,跳转到BIOS的自检程序处。

  3. BIOS执行自检程序,进行自检(POST:Power On Self Test)。

  4. BIOS枚举设备,检查设备,初始化。

  5. BIOS按照CMOS(可以理解为主板中的一个存储区域,用户可通过BIOS改写此区域的内容)中设置的引导顺序
    搜索引导设备(如先搜光盘,再搜第一块硬盘,第二块,U盘,网络设备。这取决于你boot loader的设置)。

  6. BIOS读取MBR(CHS 0/0/1) 到内存0000:7C00H中,运行MBR中的引导代码,将控制权交给MBR中的引导代码。

  7. BIOS POST程序从内存中被清理掉。(但并不是完全被清理,留下了一部分系统调用,一直存在服务于系统)。

  8. MBR中的引导程序(简称引导程序) 首先会检查MBR的最后部分是不是55 AA。
    接着扫描分区表,看分区表是否损坏,然后寻找分区表中的活动分区,确保活动分区只有1个。

  9. MBR引导程序读取活动分区,并运行活动分区的代码,并将控制权交给VBR中的代码,这部分代码就是操作系统的引导代码。
    这部分与具体的文件系统有关了,比如FAT在此处读取VBR,跳过BPB,然后引导系统

是不是脑袋晕晕的? 没关系,我们对照着MBR的三个部分,来仔细研究下这个过程:

  • 第一部分:446字节的引导程序

大体上这段引导代码进行了如下操作:

  1. 重定位自己,MBR此时已经被载入到内存的0000:7C00H,等会这个地方还有其他程序载入。
    所以引导程序首先将自身copy到0000:0600 处。接着跳转到哪里继续执行。

  2. 查找活动分区(具体是检查分区表中活跃标志位,后面讲分区表会提到。
    此处就理解检查MBR偏移0x1be, 0x1ce, 0x1de, 0x1ee的值)。
    没有活动分区或者有多个活动分区的直接打印错误信息,并且死机。

  3. 根据分区表中的CHS信息,读取活动分区的第一扇区到0000:7c00H处。

  4. 跳转到0000:7C00H处,将控制权交给活动分区引导程序。

OK,看完此处你一定有些疑问,为毛一个硬盘只能有一个活动分区?
操作系统必须装在活动分区上,我要是想装2个操作系统怎么办?
我前面说的那套东西都是标准的MBR引导程序,
你当然可以换成支持多操作系统的MBR,甚至是自己写代码替换MBR中的引导程序,都行。

好了,不纠结了亲,我们继续看下一部分。

  • 第二部分:64字节分区表

这部分为了便于理解,我们对着winhex来看。

我将4个分区(最后一个是扩展分区)分别用颜色标记出来了(开头的黄色部分是mbr的引导代码,
最后面的55 AA是MBR结束标志,大家请无视)

用DiskGenius查看一下:

 

分区表总大小64字节,一共4项,每项大家16字节。这就是为什么MBR最多只支持4个主分区的原因。

以下是分区表每项的结构(我们以第一个分区为例,红色部分):

分区状态(1字节) => 00表示非活动分区, 80表示活动分区,其他数字没什么意义
(现在明白引导程序怎么探测活动分区了吧?)。我这个硬盘有4个分区 全都是非活动分区,所以每种颜色开头都是 00

起始CHS(3字节) => (02 03 00 ) 3字节表示分区的起始柱面,磁头以及扇区。

第一个字节表示磁头 => 02磁头 (对照正确!)
第二个字节的低6位表示扇区 => 03扇区 (对照正确!)
第二字节的高2位作为高位,第三字节作为低8位,一个10位表示其实柱面 => 00 柱面(对照正确!)
文件系统标志(1字节) => (0B) 表示分区文件系统的类型。

结束CHS(3字节) => (A3 3C 01) 结束扇区标示的描述和起始扇区相同

第一字节表示中止磁头 => A3 (163) 磁头 正确!
第二字节低6位表示扇区 => 3C (00111100) 低6位为 111100 => 60 扇区 正确!
第二字节高2位作为高位,第三字节作为低8位 => 01 柱面,正确!
起始LBA (4字节) => (80 00 00 00) 起始LBA和起始CHS都描述的是扇区的起始地址,只不过起始LBA是以LBA寻址模式描述。

此分区的起始扇区LBA为0×80 (128),使用winhex的Ctrl + G跳转到128号逻辑分区


winhex顺便将LBA转换成CHS(0,2,3,正确呀,有木有!) 此处已经是FAT文件系统的VBR。

插嘴一句,关于LBA和CHS之间的转换,我前面一直没有提,我觉得没啥意思,
一是因为CHS寻址太过有限,现在基本都是LBA寻址,LBA到CHS转换属于硬盘和BIOS内部的事情。
有兴趣的同学可以google一下。

只看MBR,我们是无法转换LBA到CHS,因为我们不知道每道扇区数之类的参数。winhex此处之所以能转换是因为读取了VBR中的BPB才完成的,后面讲FAT文件系统中VBR的结构会讲。但对于BIOS来说,知道CHS就OK了,它只要传递给硬盘就能读出对应扇区的数据。这里有一个LBA 转换为CHS的算法:

LBA 2 CHS

Temp = LBA / (Sectors per Track)

Sector = (LBA % (Sectors per Track)) + 1

Head = Temp % (Number of Heads)

Cylinder = Temp / (Number of Heads)

这里面需要获得Sector per Track 和 Number of Heads,也就是每道扇区数。
如何获得?如果你的文件系统碰巧是FAT系,在VBR的BPB中正好有这个值,不过可惜的是,
FAT中的这个值基本上都是错的。对于现代磁盘来说,每个磁道的扇区数根本就不一样。
你非要获得这个值,可以调用int13中断来获取一个可计算CHS的逻辑值。

int 0×13

参数: AH 0×8

参数: DL driver index <= 第一块硬盘的id为0×80

结果:DH <= 最后一个磁头号,换句话说CH内的值 + 1就是磁头的个数

CX <= 第5位为每道最后一个扇区号,换句话说CX的低5位即为每道扇区数(扇区从1开始)
CH的高5 – 15位(即剩下的部分) 为最后一个柱面号,换句话说此值 + 1就为柱面的个数

PS:这里所说的都是逻辑上的磁头个数,扇区个数以及柱面个数,只是为了方便CHS寻址,物理上并不对应。
因为每磁道扇区的个数都不相同。如何根据LBA读取扇区,CHS读取扇区,请参看此处

  • 分区总扇区数 (4字节) => (9A 66 00 00) 表示分区是由多少个扇区构成 => 0x669A (26266) 个扇区,
    分区的大小为(每扇区512(0×200)字节):
  • 26266 * 0x200byte = 13448192byte = 12.8M 正确!

好了,分区表讲述完毕,非常简单吧。我们来思考以下几个问题。

  1. MBR中分区表只占有4项,所以造成系统最多有4个主分区。
  2. 起始和结束的CHS都用3字节表示,其中10位表示柱面,8位表示磁头,6位表示扇区,
    所以CHS寻址最大为8.4G(前面已经详细描述过了)
  3. 对于超过8.7G的硬盘,MBR中的CHS已经无法表示了,一般使用 FE FF FF 填充
    (如我disk0的这个分区),BIOS会认为这个无效地址,在normal和large模式下无视这个分区,
    而在lba模式下读取分区表中的LBA地址从而找到这个分区。
    现代一个分区,超过8G很正常,所以现代操作系统基本上都使用的是分区表中的起始LBA而非起始CHS。

由于起始LBA和分区扇区数都使用的4字节整数来表示,那么MBR格式一个分区最大为
2^32 * 512byte = 2TB 而且每个分区的起始地址都应小于2T。

举个例子,假设你有一个4T的硬盘,第一分区的起始LBA为0,大小为2TB,
那么第二个分区起始地址应在2T之后,用4字节已经无法表示了,所以第二个分区将看不见。

不过如果你有3TB的硬盘,第一分区如果为1TB,第二个分区为2TB,
那么OK(因为第二个分区起始位置小于2T,可以用4字节表示)
但如果第一个分区为2T,那么第二个分区就看不见了。

  • 第三部分:MBR结束标示(2字节)

原本没啥说的,但估计你肯定想问为什么是 55 AA ?其实我也不知道为什么,我查了挺多资料的,都没找到原因。
但55 AA绝对不是乱选的,55 二进制位 0101 0101 , AA二进制位 1010 1010。
这里有位和我们一样疑惑的哥们在stackoverflow上提问,但答案个人觉得有点牵强。

补充,关于MBR的最后一个问题,扩展分区和逻辑分区到底如何表示?

MBR中的分区表已经可以描述最多4个主分区了,其中一个主分区可以作为容器,称之为扩展分区,继续被划分成N个逻辑分区。

MBR中分区表已经包含了扩展分区的LBA,以及总扇区数,根据LBA可以找到扩展分区的起始扇区,
而这个起始扇区存放了EBR(Extend Boot Record)描述了扩展分区中的各个逻辑分区。

我们可以这么理解,将扩展分区当成一块新的硬盘。这个硬盘的第一个扇区也存在一个MBR类似的的东西。
如果我们依然选择MBR当这个新硬盘的引导扇区,那么意味这这个新硬盘还是最多只能有4个分区,
我们想让新硬盘中的分区数无限,MBR中数组结构的分区表已经无法满足要求,必须要一个链表结构的分区表。
怎么办?我们对MBR中的分区表做一点修改,分区表表第一项不变,依然描述一个分区,
分区表的第二项如果如同MBR中的扩展分区一样,描述下一个新硬盘。

(下图展示了MBR,EBR之间的关系)

简单一点描述就是:

  1. EBR和MBR结构完全相同,EBR中的引导代码一般是446字节的0,EBR分区表中的第三项和第四项全为0,没有使用。
  2. MBR的分区表中每项的LBA,要么指向主分区的第一扇区,要么指向扩展分区的EBR(EBR就在第一扇区)。
  3. EBR中分区表中的第一项指向一个逻辑分区的第一扇区,第二项指向下一个EBR (此处的LBA都是相对于EBR的LBA,不是绝对LBA)。
  4. EBR中的第二项为0的话,表明已经没有下一个逻辑分区了。

为了加深理解,我们使用winhex手动定位一下逻辑分区.如图所示,逻辑分区为F:I: J:

winhex打开Disk 2, MBR中的分区表如图:

 

扩展分区是最后一项,蓝色部分,我们只关心扩展分区起始LBA:
0x967F8 (616440) 以及扩展分区扇区个数 0×31808。 由此可知扩展分区大小为:

0×31808 * 512byte = 0×6301000 byte = 99MB (验证正确!)

使用Ctrl + G 跳转到LBA 0x967F8 (616440) 处:

如图所示,这是第一个EBR,我用红色和绿色标出了分区表中的第一项和第二项。

第一项指向第一个逻辑分区,LBA 为0x3F(63),一共0xF000个扇区。

第一个逻辑分区的大小为: 0xF000 * 512byte = 0x1E00000 byte = 30MB

LBA为 0x3F(63),说明第一个逻辑分区的偏移相对于EBR为 0x3F * 512 = 0x7E00
(由于winhex ctrl + g 没法跳转到相对LBA,所以这里我们使用alt + g 跳转到相对偏移 0x 处)

 

已经看到FAT的VBR了,说明我们找到这个分区了! 接着我们再找下一个分区,
首先找下一个EBR,相对于第一个EBR的LBA为0xF03F,相对偏移应该为:

0xF03F * 0×200 = 0x1E07E00

alt + g 跳转后,果然找到EBR!

OK,按照此方法,我们就能找到所有的逻辑分区了。

GPT 概要介绍

本来打算详细介绍下GPT,却发现此文写的实在是太长了,只能简单说说,
由于MBR 2TB以及最多4个主分区的的限制,GPT出现,GPT对分区数量没有限制,想多少都行
(网上有个说法说GPT最多支持128个分区,这种说法不对。128是windows系统的限制),
GPT支持的磁盘大小为18EB。(目前来说属于天文数字)关于GPT的更多描述请自行google(GPT我有时间再补完吧)。

 

 

 

posted @ 2013-06-27 13:49  IAmAProgrammer  阅读(1509)  评论(0编辑  收藏  举报