在Citrix PVS架构和产品中,位于最后端的存储硬盘采用的是虚拟化时代,微软开发的虚拟硬盘VHD/VHDX。VHD/VHDX格式是一种公开可用的映像格式规范,允许将硬盘封装到单个文件中,以供操作系统作为虚拟硬盘以物理硬盘的方式使用。这些虚拟硬盘能够托管本地文件系统(NTFS,FAT,exFAT和UDFS),同时支持标准硬盘和文件操作。VHD文件的最开始用于Windows7,Windows Server 2008,Virtual Server和Windows Virtual PC以及Hyper-V。随后Citrix PVS也使用了VHD虚拟硬盘。随着微软Windows Server 2012的发布以及新文件系统的开发,VHD格式需要适应这些变化。于是就在Windows Server 2012 中引入了一个新版本的 VHD 格式,称为 VHDX。新的VHDX支持最新的ReFS文件系统以及具有更大的存储容量。它还在电源故障期间提供数据损坏保护并且优化动态硬盘和差异硬盘的结构对齐方式,以防止在新的大型扇区在物理硬盘上性能降级。
我们今天来介绍下VHD/VHDX虚拟硬盘的相关技术:
1、它是如何与操作系统通信?
2、VHD/VHDX虚拟硬盘的架构是什么,和物理的硬盘相比,VHD/VHDX虚拟硬盘有何不同?
VHD/VHDX我们可以说她是一个映像文件,也可以说是一个虚拟硬盘。因为她们本身对于文件系统,表示的是一个映像文件,对于硬盘系统,表示的是一个硬盘。因此微软的VHD/VHDX虚拟硬盘我们可以给出一个定义是:使用一个映像文件来模拟物理硬盘并且存储数据。
在我们的操作系统里面,文件系统会识别VHD/VHDX映像文件为.vhd或.vhdx的文件。然后操作系统里面集成或安装的虚拟硬盘驱动系统通过加载VHD/VHDX映像文件操作,把映像文件虚拟成一个本地硬盘分区,像正常的物理分区一样进行读写操作。而卸载虚拟硬盘之后,该虚拟硬盘分区消失,唯一留下的就是映像文件。虚拟硬盘消失之后,系统就无法访问其中的文件,也不能对虚拟硬盘内存储的文件进行任何操作。
那么Citrix PVS架构下,Windows操作系统如果来识别和管理VHX/VHDX虚拟硬盘呢?
我们先来说VHD:
在Windows中对于VHD虚拟硬盘是通过VHDAPI来管理、挂载和创建的。其架构图如下所示:
在图中,基于用户模式下,通过VDS的Windows VHD API我们可以来管理、挂载、创建和销毁VHD虚拟硬盘。VDS就是Virtual Disk Service,中文简称虚拟磁盘服务,是一种Microsoft Windows服务,可根据最终用户,脚本和应用程序的请求执行查询和配置操作。该服务通过以下方式扩展Windows Server操作系统的现有存储功能:
为Windows中现有的卷和磁盘管理功能提供API。其中就包含对于VHD虚拟硬盘功能提供相应API。
在单个API下统一卷管理和硬件冗余独立磁盘阵列(RAID)管理。
但是VDS不执行以下存储管理功能:
硬件子系统管理,如温度监控或磁盘阵列性能统计的监控。
存储区域网络(SAN)架构管理,例如基于主机的适配器(HBA)连接的存储分区。
为了进一步了解应用程序或者操作系统如何来调用VDS提供的VHD API,我们来看一下VDS的架构。
VDS定义三个接口:应用层和服务之间的单个接口,以及数据层中的服务和提供商程序之间的两个接口。下图显示了VDS的架构:
N层架构使得VDS能够与文件系统功能协调,同步提供程序活动和在应用程序之间进行仲裁。在应用和提供者之间,VDS向应用提供统一的功能,即使一些底层提供者可能缺乏这样的一致性。
该服务实现了常用功能:格式化卷,添加和删除驱动器盘符或挂载文件夹,以及管理未分配的磁盘(没有分区信息的磁盘)。VDS还会向已注册的应用程序返回事件通知。
也就是说,在Citrix PVS架构下,PVS控制台可以通过调用Windows的VDS的VHD API来管理存储于PVS物理硬盘上的VHD虚拟硬盘。
我们说操作系统通过调用存储系统的VDS VHD API来实现对于VHD虚拟硬盘的管理操作,但是具体的VHD API函数则存储于也是位于用户模式下VirtDisk.dll里面,该DLL是VHD管理API的通用库。
以上的两个组件是位于用户模式下的组件,是可以供开发者进行开发自定义的模块。而位于内核模式的驱动程序,则不易被修改。在内核模式下,有三个组件:
VDrvRoot.sys :根虚拟驱动器枚举。
FsDepends.sys :嵌套卷依赖关系管理。
Vhdmp.sys :VHD解析器和依赖属性提供程序。
用户模式下VirtDisk.dll通过向下调用内核模式下的这三个驱动程序实现真正的VHD映像文件操作。
这三个驱动是虚拟设备驱动,把一个映像文件虚拟成一个磁盘设备,对虚拟设备直接进行操作;同时它们又是一个过滤驱动,它修改IRP流【应用程序的各种操作通过内核的I/O管理器转变为各种IRP请求。虚拟磁盘驱动相应文件系统驱动程序的IRP对虚拟磁盘进行相应的读写操作。】,使IRP在传递过程中两次经过文件系统。把对文件的位置请求,经过处理,指定到真实的磁盘位置,并把命令和数据传递下去。由于虚拟磁盘驱动主要在内核态修改IRP流,所以用户态的读写流程保持不变,而内核态的IRP流要两次经过文件系统:第一次经过文件系统是操作虚拟磁盘内的文件,第二次经过文件系统是操作映像文件。
说完VHD,我们来介绍VHDX:
VHDX格式由于是在WindowsServer 2012中才会被支持,而Windows Server2012对于存储功能的管理相较与2008是有所区别的。比如说在2008中不支持的硬件子系统管理,如温度监控或磁盘阵列性能统计的监控以及存储区域网络(SAN)架构管理,例如基于主机的适配器(HBA)连接的存储分区。在Windows Server 2012中均受到支持。我们可以这样理解,Wind我是 Server 2008就是一个标准的操作系统,而Windows Server 2012即是一个标准的操作系统又是一款存储操作系统。什么是存储操作系统呢?就和传统的存储控制器一样,其运行于存储控制器中,具有管理NAS和SAN功能的操作系统。即我们可以将Windows Server 2012安装到服务器中,并将该服务器当做存储控制器使用。
在Windows Server 2012中,Windows Storage Management API取取代了VDS(Virtual Disk Service)的角色和位置。也就是说在Windows Server 2012以及R2中,对于VHDX虚拟硬盘的管理是通过WindowsStorage Management API来进行的。CitrixPVS控制台通过调用WindowsStorage Management API来最终进行VHDX文件的管理。具体的读写流程和VHD是一样的,只是相对应的服务有所区别而已。
一个传统的物理硬盘抛开物理组成部分的话,物理组成部分无非就是:接口、Buffer、主控芯片、RAM、电机(SSD就是Flash颗粒)。剩下的就是一个地址序列,这个序列从0~n-1,每个地址包含512B(字节)的控件。一般我们将这些地址称作逻辑块地址(LBA),每块由512B组成。分区表的作用是:告诉系统,磁盘的分区有几个,开始位置和结束位置。磁盘分区表格式目前主要有两种MBR分区表和GUID分区表(GPT)。
VHD/VHDX虚拟硬盘是没有所谓的物理组成部分的,因此VHD/VHDX虚拟硬盘的架构其实就表现为是一个地址序列。
同样,我们先来说说VHD:
在微软的VHD 文件格式规范中【http://download.microsoft.com/download/f/f/e/ffef50a5-07dd-4cf8-aaa3-442c0673a029/Virtual%20Hard%20Disk%20Format%20Spec_10_18_06.doc】,虚拟硬盘VHD文件格式有三种类型:
固定虚拟硬盘:VHD映像文件在存储上预分配为所请求的最大大小。固定虚拟硬盘是用相同容量的VHD 文件模拟同样容量的一个虚拟硬盘,固定虚拟硬盘的VHD 文件在创建时,已分配了全部的空间,确定了大小,不随着数据的写入而改变。
可扩展方式:也称为“动态”和“可动态扩展”方式,VHD映像文件仅使用存储上足够空间来存储虚拟磁盘当前包含的实际数据。创建此类型的虚拟磁盘时,VHD API不会根据请求的最大大小测试物理磁盘上的可用空间,因此可以成功创建最大大小大于可用物理磁盘空间的动态虚拟磁盘空间。值得注意的是,VHD动态虚拟磁盘的最大大小为2,040GB。
差异方式:这种方式是建立在母盘(固定、动态或差分VHD)上的快照,必须有一个基本的VHD虚拟硬盘作为父虚拟磁盘,不能独立存在。在父虚拟磁盘之上创建差异磁盘之后,任何后续写入都写入到差异VHD映像文件中,并且不会修改父VHD映像文件。而且,差异磁盘可以在差异磁盘之上再建立差异磁盘。这也就是CitrixPVS多版本管理的技术。
上述的三种,每一种类型都有着自己的文件格式。
VHD虚拟硬盘的固定虚拟硬盘的格式:
固定虚拟硬盘的VHD 格式分为两个结构:数据区域和页脚区域。数据区域结构和虚拟硬盘相同,即数据区的扇区与虚拟硬盘的扇区顺序映射。页脚结构是所有类型的VHD 文件共有的结构,位于文件的尾部,占据一个扇区的大小(512B字节)。整个文件的大小是设定的VHD虚拟硬盘大小加上页脚大小(一个扇区),即VHD虚拟硬盘的真实大小是我们设置的值(比如40GB)加上一个扇区的大小(512B字节)。 固定虚拟硬盘所支持的硬盘大小受到操作系统的限制。例如,在FAT32文件系统上,虚拟硬盘的最大大小为4 GB。
而固定虚拟硬盘的VHD虚拟硬盘页脚区域里面有什么呢?根据VHD文件格式的规范文档说明,该页脚格式是所有的VHD类型都共享的格式,也就是该页脚区域的格式是通用的。其页脚区域规定:
硬盘页脚字段 | 大小(字节) |
Cookie(标识) | 8 |
Features(特性) | 4 |
File Format Version(文件格式版本) | 4 |
Data Offset(数据偏移量) | 8 |
Time Stamp(时间戳) | 4 |
Creator Application(应用程序创建者) | 4 |
Creator Version(创建者版本) | 4 |
Creator Host OS(创建者系统) | 4 |
Original Size(原始长度) | 8 |
Current Size(当前长度) | 8 |
Disk Geometry(磁盘参数) | 4 |
Disk Type(磁盘类型) | 4 |
Checksum(校验和) | 4 |
Unique Id(唯一ID) | 16 |
Saved State(保存状态) | 1 |
Reserved(保留) | 427 |
其完整格式如下所示:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | |
标识 | 特性 | 文件格式版本 | 数据偏移量 | |||||||||||||||||||||
时间戳 | 应用程序创建者 | 创建者版本 | 创建者系统 | 原始长度 | ||||||||||||||||||||
当前长度 | 磁盘参数 | 磁盘类型 | 校验和 | 唯一ID | ||||||||||||||||||||
唯一ID | 存态 | 保留 | ||||||||||||||||||||||
保留(427字节) | ||||||||||||||||||||||||
从图上可以看出,页脚结构共有512 字节,其定义了VHD 文件标志、类型、容量等相关信息。下面介绍页脚区域各个字段的意义。
(1)Cookie标识占8 字节。Cookie用于标识硬盘映像的原始唯一创建者。值区分大小写。固定虚拟硬盘的值是“conectix”字符串。cookie存储为8个字符的ASCII字符串,其中“c”在第一个字节,“o”在第二个字节,依此类推。
(2)特性占4 字节。这个字段说明该文件支持的特定功能,常用特性有:无、临时、保留。无特性表明该文件没有嵌入特定功能;特性为临时,表明这是一个临时的VHD 文件,当关机时会被删除;保留特性下,这一位的值必须置为1。
功能 | 值 |
未启用任何功能 | 0x00000000 |
临时 | 0x00000001 |
保留 | 0x00000002 |
(3)文件格式版本占4 字节。表明VHD 的版本信息。此字段分为主要/次要版本,并与创建文件时使用的规范的版本相匹配。最高有效的两个字节用于主要版本。最低有效两个字节是次要版本。这必须与文件格式规范匹配。对于当前规范,此字段必须初始化为0x00010000。
(4)数据偏移量占8字节。该字段保存从文件开头到下一个结构的绝对字节偏移量。此字段用于动态磁盘和差异磁盘,但不用于固定磁盘。对于固定磁盘,此字段应设置为0xFFFFFFFF。
(5)时间戳占4字节。此字段存储硬盘映像的创建时间。这是从UTC/ GMT时区2000年1月1日12:00:00:00开始计时以来的秒数。
(6)应用程序创建者占4字节。此字段用于记录哪个应用程序创建了硬盘。该字段是一个左对齐的文本字段。它使用单字节字符集。如果硬盘由Microsoft Virtual PC创建,则在此字段中写入“vpc”。如果硬盘映像由MicrosoftVirtual Server创建,则在此字段中写入“vs”。其他应用程序应使用自己的唯一标识符。每个应用程序在Windwos中都会有一个自己唯一的标识符。
(7)创建者版本占4字节。此字段保存创建硬盘映像的应用程序的主要/次要版本。
(8)创建者系统占4字节。此字段存储在其上创建此磁盘映像的主机操作系统的类型。
(9)原始长度占8字节。此字段存储创建时从虚拟机的角度来看的硬盘大小(以字节为单位)。此字段用于信息目的。
(10)当前长度占8字节。此字段从虚拟机的角度存储硬盘的当前大小(以字节为单位)。在固定虚拟硬盘格式下,此值与创建硬盘时的原始大小相同。在动态方式下,此值可根据硬盘是否扩展而更改。
(11)硬盘参数占4字节。此字段存储硬盘的磁道,磁头和每磁道的扇区值。
磁盘参数字段 | 大小(字节) |
Cylinder | 2 |
Heads | 1 |
Sectors per track/cylinder | 1 |
当硬盘被配置为ATA硬盘时,ATA控制器使用CHS值(即,磁道,磁头,每磁道的扇区)来确定磁盘的大小。当用户创建具有一定大小的硬盘时,虚拟机中的硬盘映像的大小小于用户创建的硬盘映像的大小。这是因为从硬盘大小计算的CHS值向下取整。
(12)磁盘类型占4字节。
磁盘类型字段 | 值 |
无 | 0 |
Reserved (deprecated) | 1 |
Fixed hard disk | 2 |
Dynamic hard disk | 3 |
Differencing hard disk | 4 |
Reserved (deprecated) | 5 |
Reserved (deprecated) | 6 |
(13)校验和占4字节。此字段只检验VHD 文件的页脚区域,不包括数据部分。校验和是由页脚中除去校验和字段的信息之后计算得到的。如果校验和出错,则认定文件损坏。
(14)唯一ID占16字节。每一块硬盘都有一个唯一ID用于识别硬盘。该唯一的ID是一个128位的通用唯一标识符(UUID)。此字段用于将父硬盘映像与其差异硬盘映像进行关联。
(15)已保存状态占1字节。此字段保存一个字节标志,描述系统是否处于保存状态。如果硬盘处于保存状态,则该值设置为1。无法在保存状态的硬盘上执行压缩和扩展操作。
(16)保留占427字节。此字段顾名思义的保留字段,用于今后可能的参数以及字段扩展,其存储的数据全部是0。它的大小是427字节。
2、可扩展方式(动态)虚拟硬盘
由于可扩展的VHD虚拟硬盘的动态性,因此不同于固定虚拟硬盘的VHD的格式。可扩展的VHD 大小随着写入的数据而动态变化。比如创建一个60GB的可扩展的VHD文件时,它的初始大小可能仅为几百MB,但是随着后期数据的不断写入,可扩展的VHD文件逐渐增加,并最终达到60GB的最大值。这中间存储的数据是随机的,杂乱无章的。因此就必须得有一个类似于记录本一样的东西来记录后来增加的这些数据是存储于那个柱面的那个扇区上。
VHD可扩展的虚拟硬盘格式在规范文档中表示如下:
逻辑结构图表示如下:
由上图可看出,一个扩展的VHD文件由页脚备份区域、头部区域、块分配表、数据区和页脚区域组成。页脚备份区域是对页脚区域的备份,位于文件的第0 扇区;头部区域是1024字节的固定长度,位于文件的第1、2 扇区;块分配表位于头部区域之后,每个条目占4 字节,其随着数据的增长而动态扩展扇区,不固定长度;数据区位于块分配表之后,每个数据块包括扇区位图和块数据,分别为512 字节和2 MB,同样其随着数据的增长而动态扩展扇区,不固定长度;页脚区域是512字节,与固定虚拟硬盘VHD的页脚区域是一样的大小,只是其中关键值不同,其位于文件的最后一个扇区;
是对页脚区域的备份,其数据和页脚区域一摸一样,因此了解了页脚区域就行,页脚区域在上述的固定虚拟硬盘中以及进行了详细计介绍。
可扩展的VHD的头部区域表示文件的概况,包括数据块大小,块分配表位置和数量,以及关于差分等重要信息。
在VHD格式规范文档中,可扩展的VHD文件头部的格式如下表所示:
可扩展磁盘头部字段 | 大小(字节) |
Cookie(标识) | 8 |
Data Offset(数据偏移量) | 8 |
Table Offset(表偏移量) | 8 |
Header Version(头部版本) | 4 |
Max Table Entries(最大表条目) | 4 |
Block Size(块大小) | 4 |
Checksum(校验和) | 4 |
Parent Unique ID(母盘唯一ID) | 16 |
Parent Time Stamp(母盘时间戳) | 4 |
Reserved(保留) | 4 |
Parent Unicode Name(母盘Unicode名称) | 512 |
Parent Locator Entry 1(母盘定位器条目1) | 24 |
Parent Locator Entry 2(母盘定位器条目2) | 24 |
Parent Locator Entry 3(母盘定位器条目3) | 24 |
Parent Locator Entry 4(母盘定位器条目4) | 24 |
Parent Locator Entry 5(母盘定位器条目5) | 24 |
Parent Locator Entry 6(母盘定位器条目6) | 24 |
Parent Locator Entry 7(母盘定位器条目7) | 24 |
Parent Locator Entry 8(母盘定位器条目8) | 24 |
Reserved(保留) | 256 |
其逻辑结构如下图所示:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | |
标识 | 数据偏移量 | 表偏移量 | ||||||||||||||||||||||
头部版本 | 最大表条目 | 块大小 | 校验和 | 母盘唯一ID | ||||||||||||||||||||
母盘唯一ID | 母盘时间戳 | 保留 | 母盘Unicode名称 | |||||||||||||||||||||
母盘Unicode名称(512B字节) | ||||||||||||||||||||||||
母盘定位器条目1 | ||||||||||||||||||||||||
………… | ||||||||||||||||||||||||
母盘定位器条目8 | ||||||||||||||||||||||||
保留(256B字节) | ||||||||||||||||||||||||
下面提供了可扩展VHD虚拟硬盘头部字段的详细说明。
(1)Cookie标识占8字节。此字段保存值为“cxsparse”。此字段标识头部是否为合法的头部字段。
(2)数据偏移量占8字节。此字段包含硬盘映像中下一个结构的绝对字节偏移量。目前未被现有任何所格式使用,默认设置为0xFFFFFFFF。
(3)表偏移量占8字节。此字段存储文件中块分配表(BAT)的绝对字节偏移量。由于前两个字段为固定长度,因此块分配表总是从0x600 处开始,字段固定为0x600。
(4)头部版本占4字节。此字段用于存储可扩展VHD虚拟硬盘头部的版本。该字段分为主/次版本。最低有效两个字节表示次版本,最高有效两个字节表示主版本。这必须与文件格式规范匹配。对于本规范,此字段必须初始化为0x00010000。主版本将仅在标头格式修改为不再与产品的旧版本兼容时增加。
(5)最大表条目占4字节。此字段保存BAT中存在的最大条目。这应该等于磁盘中的块数(即磁盘大小除以块大小)。
(6)块大小占4字节。该字段定义了块的容量。块是动态和差异硬盘的扩展单元。它以字节存储。此大小不包括块位图的大小。它只是块的数据部分的大小。每个块的扇区必须总是2的幂次方。默认值为0x00200000(表示块大小为2 MB)。
(7)校验和占4字节。此字段持有动态头部的基本校验和。它是除去头部字段之外其他所有字段之和的一个补码,和页脚区域的校验和计算是一样的。如果校验和验证失败,则会判定文件已损坏。
(8)母盘唯一ID占16字节。此字段用于区分硬盘。差异硬盘存储母盘的128位UUID。可扩展的VHD 虚拟硬盘中这个字段置零。
(9)母盘时间戳占4字节。此字段存储母盘的修改时间戳。这是从时区UTC / GMT 2000年1月1日12:00:00:00开始计算以来的秒数。
(10)保留占4字节。此字段置为零。
(11)母盘Unicode名称占512字节。此字段包含母盘文件名的Unicode字符串(UTF-16)。
(12)母盘定位器条目占192字节(8个条目,每个条目24字节)。这些条目在存储差异硬盘的母盘定位器的文件中存储绝对字节偏移量。用来在不同平台之间迁移VHD文件。此字段仅用于差异磁盘,对于动态磁盘设置为零。
下表描述了每个定位器条目内的字段。
母盘定位器表字段 | 大小(字节) |
Platform Code | 4 |
Platform Data Space | 4 |
Platform Data Length | 4 |
Reserved | 4 |
Platform Data Offset | 8 |
平台代码占4字节。平台代码描述了哪种平台特定的格式用于文件定位器。对于Windows,文件定位器存储为路径(例如,“c\disksimages\ParentDisk.vhd”)。在Macintosh系统上,文件定位器是包含“别名”的二进制大对象(blob)。母盘定位器表用于支持跨平台移动硬盘映像。
一些当前的平台代码包括以下:
Platform Code | Description |
None (0x0) | |
Wi2r (0x57693272) | [deprecated] |
Wi2k (0x5769326B) | [deprecated] |
W2ru (0x57327275) | Unicode pathname (UTF-16) on Windows relative to the differencing disk pathname. |
W2ku (0x57326B75) | Absolute Unicode (UTF-16) pathname on Windows. |
Mac (0x4D616320) | (Mac OS alias stored as a blob) |
MacX(0x4D616358) | A file URL with UTF-8 encoding conforming to RFC 2396. |
平台数据空间占4字节。此字段存储存储母盘定位器所需的512字节扇区数。
平台数据长度占4字节。此字段存储母盘定位器的实际长度(以字节为单位)。
保留占4字节。此字段必须设置为零。
平台数据偏移占8字节。该字段存储存储平台特定文件定位器数据的绝对文件偏移量(以字节为单位)。
(13)保留占256字节。初始化为零。
块分配表简称BAT,是可扩展VHD文件格式中一个重要的结构,存储了虚拟硬盘到VHD文件的地址映射信息。它由可扩展虚拟硬盘头部的“表偏移”字段指向。
BAT的大小是在创建硬盘期间计算的。BAT中的条目数是完全展开时存储磁盘内容所需的块数。例如,使用2 MB块的基本单位数据块来存储2GB数据,磁盘映像需要1024个BAT条目。 每个条目都是4个字节长,那么大小就为4096个字节。,从块分配表的第1个字节(0x600)开始,所有未使用的表条目都初始化为0xFFFFFFFF。
BAT总是扩展到扇区边界。 可扩展磁盘头部中的“最大表条目”字段指示有多少条目有效。
BAT的条目存储了虚拟硬盘的块地址映射到VHD文件的绝对扇区偏移量,表示虚拟硬盘的块中的数据存储在VHD 文件中以该扇区开始的数据块内。如果向虚拟硬盘的块写入数据,那对应的块分配表的条目为该块在VHD文件分配空间;如果虚拟硬盘的块没有数据写入,那对应的块分配表条目就不分配空间。这保证了虚拟硬盘通过块分配表的动态更新可以随时向VHD 文件写入数据,也阐明了VHD文件容量的动态变化。
其具体的流程图如下图所示:
上图中描述了虚拟硬盘的数据块到VHD文件的数据块的映射关系。块分配表的条目与虚拟硬盘块的数目是保持一致的,且硬盘的第n个块对应块分配表的条目n,也就是一一对应的关系,这样的好处是方便的进行读取的时候按顺序查找所存储的数据在哪个数据块上。但VHD文件的数据区的数据块的顺序不与此对应。图中,块分配表的条目0为虚拟硬盘的第0块分配到VHD文件中以某扇区开始的第1块,即写入虚拟硬盘第0 块的数据会存储在VHD 文件的某扇区第1块数据块区域,这里的某扇区即是VHD文件存储在真实硬盘上的扇区。因此我们就可以理顺VHD虚拟硬盘快分配表的工作模式了:
1)、数据写入到虚拟硬盘数据块。数据首先写入到VHD虚拟硬盘的数据块中;
2)、记录块分配表。然后根据其数据块写入的对应块分配表,记录相应的虚拟硬盘数据块到VHD文件的数据区域的数据块的地址映射信息。
数据块由扇区位图和数据组成。对于VHD可扩展硬盘,扇区位图指示了哪些扇区包含有效数据(值为1),以及哪些扇区未被使用(值为0)。对于差异硬盘,扇区位图指示哪些扇区位于差异磁盘(值为1)内,哪些扇区位于母盘(值为0)中。位图总计有512字节即一个扇区大小。
块是扇区倍数的乘方。默认情况下,块的大小为4096个512字节扇区(2 MB)。虚拟硬盘的所有块必须具有相同的大小。此大小在可扩展虚拟硬盘头部的“块大小”字段中定义。
位图中的相应位为零的块中的所有扇区必须在虚拟硬盘上包含512字节的零。访问磁盘映像的软件可以利用该假设来提高性能。
虚拟硬盘的块经块分配表分配空间后,指向数据块中的扇区位图,通过查看扇区位图的每一位,确认块数据区的使用情况,然后进行对数据的操作。
明白了上述的基本知识之后,我们来说说如何实现可扩展的虚拟硬盘?
首先,数据块按需分配。创建可扩展的虚拟硬盘时,最初不为其分配数据块。新创建的映像仅包含前面描述的数据结构(包括可扩展的虚拟硬盘头部和块分配表BAT)。
当数据写入映像时,可扩展的虚拟硬盘将为写入的数据扩展一个个新的数据块。然后BAT被一一对应进行更新,以包含在映像内分配的每个新数据块的偏移量。
VHD有一个计算公式可以让虚拟硬盘知道其将虚拟硬盘的数据块中的扇区映射到VHD映像文件块中的那个扇区。
要从引用的扇区号计算块号,该公式如下所示:
BlockNumber = floor(RawSectorNumber / SectorsPerBlock)
SectorInBlock = RawSectorNumber%SectorsPerBlock
BlockNumber用作BAT的索引。 BAT条目包含块位图开始的绝对扇区偏移,后面跟块的数据。以下公式可用于计算数据的位置:
ActualSectorLocation = BAT[BlockNumber] + BlockBitmapSectorCount + SectorInBlock
以这种方式,可以以任何顺序分配块,同时保持其通过BAT的排序找到数据。
当新分配一个数据块时,页脚区域必须被推回到文件的末尾。
本文出自 “我拿流年乱了浮生” 博客,请务必保留此出处http://tasnrh.blog.51cto.com/4141731/1874774
原文地址:http://tasnrh.blog.51cto.com/4141731/1874774