Labs简介大型操作系统(如Linux)的内存管理内容非常丰富,内存虚拟化技术是在OS内存管理的基础上叠加的。层的复杂性需要对虚拟内存进行重新虚拟化。本文将从“概述”、“软硬件解决方案”和“内存管理”四个方面来探讨内存虚拟化技术。一、内存虚拟化概述所谓内存虚拟化,是指多个虚拟机之间如何共享物理内存,如何动态分配。在《x86架构基础》一文中,操作系统介绍了物理服务器内存管理的知识。它的本质是将物理内存地址映射到一个线性地址空间,也叫逻辑地址空间。应用程序通过段页查询访问内存物理地址的机制完成。而这个线性地址空间或者逻辑地址空间本身就是物理内存的虚拟化呈现。在虚拟化环境中,分配给虚拟机的内存与操作系统中线性地址空间的实现非常相似。操作系统负责维护虚拟页码到真实页码的映射,并将这个映射信息保存到页表中。在x86架构的CPU中,内存管理单元MMU和TLB这两个模块负责实现和优化虚拟内存的性能。详见《DPDK技术在电信云中最佳实践》系列文章。操作系统对其物理内存有两个主要的基本理解:物理地址从0开始,内存地址是连续的(至少在一些大粒度上)。如上图所示,VMM和guest操作系统在对物理内存的理解上存在冲突,这使得实际拥有物理内存的VMM必须对guest操作系统访问的内存进行一定程度的虚拟化系统。换句话说,VMM负责虚拟化MMU并为客户操作系统提供连续的“物理”地址空间。Address,GVA)映射到虚拟机物理地址(GuestPhysicalAddress,GPA),但需要VMM将虚拟机物理地址映射到物理机物理地址(HostPhysicalAddress,HPA)。因此,内存虚拟化的本质是将物理机真实的物理内存统一管理,打包成多个虚拟内存供多个虚拟机使用。内存虚拟化的核心是引入了一层新的地址空间——客户端物理地址空间。客户端以为自己运行在真实的物理地址空间,实际上是通过VMM访问真实的物理地址。VMM中保存了一个客户机地址空间和物理机地址空间的映射表。虚拟化系统包括三层内存地址空间:虚拟机虚拟地址GVA、虚拟机物理地址GPA和物理机物理地址HPA。因此,原本由MMU完成的线性地址到物理地址的映射不再令人满意,必须访问VMM来完成三层地址的映射维护和转换。GVA:指GuestOS为其应用程序提供的线性地址空间。GPA:由VMM抽象出来,虚拟机看到的伪物理地址空间。HPA:真机地址,即出现在地址总线上的地址信号。为了实现上述映射和转换关系,主要有两种方案:软件方案---影子页表和硬件方案---Intel的EPT和AMD的RVI。2.内存虚拟化软件解决方案2.1MMU半虚拟化(MMUParavirtualization)Xen主要采用这种方法。MMU半虚拟化的主要原理是:当GuestOS创建一个新的页表时,VMM使用为它维护的空闲内存分配页面和寄存器。随后,GuestOS对页表的写操作会落入VMM进行校验和转换;VMM检查页表中的每一项,以确保它们只映射到属于虚拟机的机器页,并且不包含页表页。可写地图。然后,VMM根据自己维护的映射关系PA-MA,将页表项中的虚拟机逻辑地址VA替换为对应的机器地址MA。最后将修改后的页表加载到MMU中,MMU可以直接根据修改后的页表完成虚拟地址VA到机器地址MA的转换。这种方法的实质是将映射关系VA-MA直接写到GuestOS的页表中,以替代原来映射的VA-PA映射关系。2.2影子页表与MMU半虚拟化相比,大多数虚拟化厂商在VMM中还使用了一种叫做影子页表(ShadowPageTable)的技术来实现上述功能。对于每个虚拟机的主页表(PrimaryPageTable),VMM维护了一个影子页表来记录和维护GVA和HPA的映射关系。影子页表映射关系影子页表包括以下两种映射关系,1)GVA>>>GPA,虚拟机操作系统负责维护虚拟机逻辑地址到虚拟机物理地址的映射关系,以及VMM可以从虚拟机主页表中获取这个映射关系。2)GPA>>>HPA,VMM负责维护虚拟机物理地址到物理机物理地址的映射关系。通过这种二级映射的方式,VMM为GuestOS的每一个页表维护一个影子页表,并将GVA-HPA映射关系写入影子页表,GuestOS页表的内容保持不变不变。然后,VMM将影子页表写入MMU。同时有效地控制了虚拟机可访问的内存边界。而且,使用TLB来缓存影子页表的内容,可以大大提高虚拟机访问内存的速度。影子页表的维护会带来较大的时间和空间开销。时间开销主要体现在GuestOS在构造页表时没有主动通知VMM。VMM必须等到GuestOS发生页面错误(GuestOS必须更新主页表),然后分析页面错误的原因,然后为它完成影子页面。表面。空间开销主要体现在VMM需要支持多个虚拟机同时运行。每个虚拟机的GuestOS通常会为运行在其上的每个进程创建一个页表系统。因此,影子页表的空间开销会随着进程数的增加而迅速增加。为了平衡时间开销和空间开销,现在普遍使用影子页表缓存(ShadowPageTableCache)技术,即VMM在内存中维护一些最近使用的影子页表,只有当影子页表不能在缓存中找到,建立一个新的影子页表。目前主要的虚拟化技术采用影子页表缓存技术。3、内存虚拟化的硬件解决方案为了解决上述影子页表带来的开销问题,除了使用影子页表缓存技术(虽然该技术可以避免部分时间开销,但空间开销仍然存在),Intel和AMD都提供了自己的MMU虚拟化解决方案:Intel在Nehalem微架构CPU中引入了扩展页表(EPT)技术;AMD在四核皓龙CPU快速虚拟化指数(RapidVirtualizationIndex,RVI)技术中引入了扩展页表(EPT)技术。RVI和EPT虽然在具体实现细节上有所不同,但在设计理念上是完全一致的:通过在物理MMU中保存两个不同的页表,在硬件中完成内存地址的两次映射,从而达到提升性能的目的。具体来说,MMU中管理着两个页表。第一个是GVA>>>GPA,由虚拟机决定;二是GPA>>>HPA,对虚拟机透明,由VMM决定。根据这两个映射页表,CPU中的pagewalker可以生成最近访问过的key-value键值对,缓存到TLB中(类似于影子页表缓存技术的思想)。另外,VMM在影子页表中维护的GPA>>>HPA映射关系是由一组新的数据结构ExtendedPageTable(也叫NestedPageTable)保存的。由于GPA>>>HPA的映射关系非常固定,不需要在虚拟机创建或修改页表时更新,所以VMM不需要在虚拟机更新页表时进行干预。VMM不需要参与虚拟机上下文切换,虚拟机可以自行修改GVA>>>GPA的页表。我们以英特尔EPT技术为例。IntelEPT是IntelVT-x提供的内存虚拟化支持技术,其基本原理如下图所示。EPT在原有CR3页表地址映射的基础上,引入EPT页表实现另一种映射。例如:假设client页表和EPT页表都是4级页表,CPU完成一次地址转换的基本过程如下:CPU首先查找client指向的L4页表CR3寄存器。clientCR3寄存器给出GPA,于是CPU通过EPT页表将clientCR3中的GPA转换为HPA:CPU首先查找EPTTLB,如果没有对应的记录,则进一步查找EPT页表,如果not,CPU抛出EPTViolation异常,交给VMM处理。CPU获得L4页表(简称HPA)的地址后,CPU根据GVA和L4页表项的内容获得L3页表项的GPA。如果L4页表中GVA对应的表项显示为“pagefault”,则CPU产生PageFault,直接交给客户操作系统处理。CPU获得L3页表项的GPA后,通过查询EPT页表将L3GPA转换为HPA。同样,CPU会依次查询L2和L1页表,得到GVA对应的GPA,然后最后一次查询EPT页表,得到HPA。如上图所示,CPU需要查询EPT页表5次,每次查询需要4次内存访问。这导致在最坏的情况下共有20次内存访问。EPT硬件通过增加EPTTLB的大小来最小化内存访问。4、内存虚拟化管理在虚拟化环境中,内存是保证虚拟机性能的关键因素。如何尽可能的提升虚拟机的性能,提高内存利用率,减少虚拟机上下文切换的内存开销,还是很复杂的,这就引入了内存虚拟化管理的问题。和介绍CPU虚拟化管理一样,我们还是用例子来说明内存虚拟化管理。以VMware的ESX解决方案为例。在硬件支持的内存虚拟化技术出现之前,ESX/ESXi使用影子页表将虚拟机的虚拟地址快速转换为物理机的物理地址。当Intel和AMD分别推出EPT和RIV技术后,ESX/ESXi迅速转向硬件支持,以提高内存虚拟化的性能。4.1内存复用技术在虚拟内存管理方面,ESX/ESXi实现了主机内存过度分配的目标:即多个虚拟机的总内存分配大于物理机的实际内存容量。如下图所示,一台只有4GB物理内存的Host可以同时运行三台2GB内存的虚拟机。宿主机内存超分配功能是指VMM必须能够有效回收虚拟机中不断释放的内存,在有限的内存容量内尽可能提高内存利用率。因为HostMemory和GuestMemory之间并不是一一对应的。通过HostMemoryover-allocation技术,可以使某台Host上的虚拟机内存大于宿主机内存。这与CPU虚拟化不同。但是,在实现over-provisioning技术时,需要考虑主机的性能,不能太大。一般的过度配置限制是主机内存的50%。要实现主机内存超分配,必须通过内存复用技术来实现。目前常用的内存复用技术有三种:零页共享技术、内存气球回收技术和内存置换技术。4.1.1零页(透明页)共享技术当多个虚拟机运行时,一些内存页的内容可能完全相同,例如:没有数据的零页。这提供了在虚拟机之间甚至虚拟机内部共享内存的可能性。例如:当多个虚拟机运行相同的操作系统、相同的应用程序或包含相同的用户数据时,可以共享那些包含相同数据的内存页。基于这个原理,VMM可以通过回收冗余数据的内存页,只维护一个被多个虚拟机共享的内存副本来实现这个功能。华为FusionCompute的零页共享技术原理是这样的:用户进程定时扫描虚拟机的内存数据,如果发现数据内容全为零,则修改PA到MA映射的形式指向特定的零页。这样在物理内存中只保留一份零页,虚拟机的所有零页都指向这个页,从而达到节省内存资源的目的。当零页数据发生变化时,Xen动态地为虚拟机分配一页内存,这样修改后的数据就可以存放在内存页中。因此,对于GuestOS来说,整个零页面共享技术是完全不知情的。在VMware的ESX解决方案中,也有同样的技术。在VMwareESX/ESXi中,检测页面数据是否冗余是通过哈希来实现的。首先,VMM维护了一个全局哈希表,表中的每一项记录了一个物理页数据的哈希值和页码。当对虚拟机进行页面共享扫描时,VMM会为虚拟机物理页面的数据计算一个哈希值,遍历全局哈希表,匹配是否存在具有相同哈希值的条目。当找到匹配的表项时,逐位比较页面数据的内容,避免由于哈希冲突导致页面内容不同的可能性。一旦确定页面数据完全一致,就会修改逻辑地址和物理地址的映射关系,即逻辑地址到包含冗余数据的物理地址的映射关系(虚线所示)上图中)将更改为共享物理地址的映射关系,并回收冗余物理页。这个过程对虚拟机操作系统是完全透明的。因此,包含敏感数据的共享页面部分不会在虚拟机之间泄露。虚拟机对共享页进行写操作时,是通过一种“写时复制”(Copy-on-Write)技术实现的。具体来说,任何对共享页面的写操作都会导致页面错误(MinorPageFault)。当VMM捕获到这个错误时,它会为发起写操作的虚拟机创建一个页面的私有副本,并将写入的逻辑地址映射到这个私有副本页面。这允许虚拟机安全地写入,而不会影响共享该页面的其他虚拟机。与非共享页的写操作相比,这种处理方式虽然确实会造成一些额外的开销,但一定程度上提高了内存页的利用率。4.1.2内存气球回收技术内存气球回收技术也称为内存气泡技术。基于气球回收法的内存管理机制与页面共享完全不同。在虚拟化环境中,VMM会在虚拟机启动后为虚拟机分配一次内存。由于虚拟机没有意识到自己运行在虚拟化平台上,所以它会一直运行在分配的内存空间中,而不是主动释放分配的物理内存给其他虚拟机。因此,VMM需要一种机制,让虚拟机主动释放空闲内存,归还给物理机,再由VMM分配给其他需要的虚拟机。而且,当内存资源需求紧张时,它还可以“取回”自己从物理机释放出来的那部分内存。华为FusionCompute内存气泡技术的原理是这样的:hypervisor利用用户虚拟机预装的前端驱动“窃取”guestOS的内存贡献给VMM供其他虚拟机使用.将气泡中的内存用于特定的虚拟机。内存泡沫的本质是将相对空闲的虚拟机内存释放给内存使用率高的虚拟机,从而提高内存利用率。在VMware的ESX解决方案中,也有类似的技术。内存释放过程示意图上图(a)中,VMM的四个页面映射到虚拟机的内存页面空间,其中左边两个页面被应用程序占用,另外两个是标有星号。该页面在内存空闲列表中。当VMM要从虚拟机中回收内存时,比如回收两个内存页,VMM会把balloon-driventargetinflationsize设置为两个page。Balloon驱动获取目标扩展值后,会在虚拟机内部申请两页内存,如上图(b)所示,调用虚拟机操作系统的接口将这两页标记为“固定”。也就是不能再分配了。内存申请完成后,Balloondriver会将这两页的页号通知VMM,以便VMM找到对应的物理页号并回收。上面(b)中的虚线表示从虚拟机分配的这两个页面的状态。由于被释放的页面在被释放之前已经在虚拟机的空闲列表中,因此没有进程会读取或写入该页面。如果虚拟机的进程接下来需要重新访问这些页面,那么VMM可以像往常一样为虚拟机分配新的物理内存。当VMM决定缩小气球尺寸时,通过设置较小的目标膨胀值,气球驱动程序将返回已“固定”到虚拟机的页面。通过气球回收方法,VMM成功地将系统内存压力转移到各个虚拟机,尽管虚拟机的负载略有增加。当气球驱动发起内存申请请求时,虚拟机操作系统决定是否换出虚拟机物理内存以满足气球驱动的内存申请请求。如果虚拟机有足够的空闲内存,气球驱动请求的内存不会影响虚拟机的性能;如果虚拟机的内存已经紧张,则由虚拟机的操作系统决定换出哪些内存页以满足气球驱动请求。因此,气球回收方式巧妙地利用了各个虚拟机操作系统的内存分页机制来决定哪些页面要释放给物理机,而不是由VMM来决定。气球恢复方法要求虚拟机操作系统必须安装气球驱动。在VMware的ESX/ESXi产品中,就是VMwareTool。另外,气球回收方式需要一定的时间来回收内存,不能立即满足系统的需求。4.1.3内存替换技术页面共享机制和气球回收方法都从不同的角度尽可能提高虚拟机的内存利用率,从虚拟机中回收可重用或空闲的内存。但是,这两种方法都不能在短时间内满足系统内存回收的要求:页面共享取决于页面的扫描速度以及是否有可以共享的页面;气球回收规则取决于虚拟机操作系统对气球驱动程序请求的内存时间的响应。如果这两种温和的方法都不能满足需求,VMM就会采用内存交换机制,即从虚拟机中强行夺回内存,这就是内存置换技术。华为FusionCompute与VMwareESX/ESXI的内存替换技术示意图如下:通过VMM实现页面请求功能。这时候GuestOS就像进程一样,可以在VMM内存不足的时候换出到宿主机磁盘上,也就是把虚拟机长时间没有访问的内存内容换到存储上,并建立映射,然后在虚拟机再次访问内存内容时替换。这种方法对虚拟机也是透明的,即虚拟机是不知道的。具体来说,VMM会在每个虚拟机启动时创建一个单独的分页文件(SwapFile)。必要时,VMM会主动将虚拟机的物理内存页交换到页面文件中,释放出来供其他虚拟机使用。内存交换机制是VMM在短时间内缓解内存压力的有效方法,但这种方法很可能会严重降低VMM的性能。由于VMM不了解虚拟机的内存使用情况,而这种方式对虚拟机是透明的,强制内存交换可能会触发虚拟机操作系统内部的一些分页机制。例如,虚拟机操作系统永远不会换出内核的内存页,VMM不知道哪些页正在被内核使用。一旦这些页面被换出,虚拟机的性能将受到严重损害。4.2内存回收下面以VMwareESX为例,结合以上三种内存复用技术,介绍内存回收机制。一般来说,ESX会根据空闲内存的百分比为物理机的空闲内存状态设置四种状态,分别是:高(6%)、中等(4%)、重(2%)和低(1%).ESX会根据这四种状态选择上述三种内存恢复机制。默认情况下,ESX会启用页面共享机制,因为页面共享机制可以以较小的开销提高内存利用率。何时启用气球回收和分页取决于系统当前的内存状态。当内存状态为“high”时,很明显此时虚拟机的内存总使用量小于物理机的内存容量。因此,无论虚拟机的内存是否已经过载,VMM都不会使用ballooning或changingpages的方法。回收内存。然而,当物理机的空闲内存状态下降到“平稳”状态时,VMM开始使用气球回收的方法。事实上,气球回收方法是在空闲内存百分比高于4%的“平坦”阈值之前启动的,因为该方法总是需要一段时间才能在虚拟机中分配一些内存。通常,气球回收方法可以及时将空闲内存比例的阈值控制在“平滑”状态之上。一旦气球回收方式无法及时回收内存,空闲内存下降到“heavy”状态,即空闲内存比例低于2%,则VMM将重启内存交换机制,强制从中回收内存虚拟机。使用这种方法,VMM可以快速回收内存并将空闲内存比率控制回“平坦”状态。在最坏的情况下,如果空闲内存状态低于“低”状态,即空闲内存比例低于1%,那么VMM将继续使用内存交换方式,同时,那些消耗内存值超过内存配置值的虚拟机挂掉。在某些情况下,VMM可能不会考虑物理机的空闲内存状态,但仍然会激活物理机的内存回收机制。例如,即使整个系统中物理机的空闲内存状态为“高”,如果某个虚拟机的内存使用量超过了其指定的内存限制,VMM将启动气球回收方法,并在必要时进行内存交换.逐出机制从虚拟机回收内存,直到虚拟机的内存低于指定的内存限制。4.3内存QoS保证在虚拟化系统中,内存虚拟化的QoS保证包括两个基本特征:预留和共享。内存预留:虚拟机预留的最小内存。保留的内存将由VM独占使用。也就是说,一旦内存被虚拟机预留,即使该虚拟机的实际内存使用量没有超过预留量,其他虚拟机也无法抢占该虚拟机的空闲内存资源。即以上三种内存复用技术对该虚拟机不生效。内存共享:适用于以上三种资源复用场景,内存资源按比例分配。以一台6G内存规格的主机为例,假设其上运行着三台4G内存规格的虚拟机VMA、VMB、VMC。内存份额分别为20480、20480、40960,所以内存分配比例为1:1:2。当三个虚拟机的内部压力逐渐增大时,该策略会按照三个虚拟机的份额按比例分配和调整内存资源。最后三台虚拟机获得的内存量稳定在1.5G/1.5G/3G。?还有一点需要注意:内存共享只有在虚拟机之间发生资源竞争时才会生效。如果没有竞争,需要它的虚拟机就可以独占物理内存。但是,内存QoS没有像CPUQoS那样设置上限?这是因为分配给虚拟机的内存大小是它的内存上限。
