Chinaunix首页 | 论坛 | 博客
  • 博客访问: 809505
  • 博文数量: 850
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 9960
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-04 11:03
文章分类

全部博文(850)

文章存档

2011年(1)

2008年(849)

我的朋友

分类: 服务器与存储

2008-07-10 11:10:14

3.3.2 时间和定时器

    Xen为每个guest OS提供了真实时间,虚拟时间和挂钟时间(wall-clock time)等三个概念。真实时间是以纳秒为单位给出的,是从机器引导起来开始计算的时间,它记录的是精确的处理器执行的时钟周期数,时钟周期能够被外部时钟源锁频(例如,通过NTP时间服务)。domain的虚拟时间只是在它运行的时候才会被记入:这主要供guest OS的调度器使用来确保guest OS上的应用进程能够正确地共享时间片。最后,挂钟时间是一个偏移,用于加到当前的真实时间上。挂钟时间能够被调整(//比如在各个guest OS中的时间可以不同,有的是上午九点,有的是下午三点,改的就是这个值),同时不会影响真实时间的流逝。

    每一个guest OS能够对一对警钟定时器进行编程,一个用于真实时间,另一个用于虚拟时间。guest OS能够维护内部的定时器队列(//很多应用程序都有定时需求,真实的或者虚拟的,特别是网络应用;guest OS要对这些定时需求排队以确定谁的时间要求最紧迫,然后就尽量依次满足它们;只要有一个定时需求没被满足,即超时了,那么系统就产生异常)并使用Xen提供的警钟定时器来触发最早的超时。超时事件将会使用Xen事件机制来递交。

    3.3.3虚拟地址转换

    和其它子系统一样,Xen也努力以尽可能小的开销实现存储访问的虚拟化。正如2.1.1中讨论的,由于x86架构使用的是硬件页表,因此达到这个目标有些难度。VMware中使用的方法是为每个guest OS提供虚拟的页表,这个页表对于存储管理单元(MMU)是不可见的[10].然后由hypervisor负责陷入对虚拟页表的访问,确认更新,再将这些改变传播到虚拟页表和MMU可见的“影子”页表(//“影子”页表在第2部分提到过)。这大大增加了这个guest

    OS操作的代价,比如创建一个新的虚拟地址空间,需要对“访问过的”和“脏的”比特位上的硬件更新进行显式地传播。

    之所以完全虚拟化要强迫使用影子页表,是因为它要给出连续的物理内存的假象,而Xen就不拘泥于此。实际上,Xen只需要考虑对页表的更新,来防止guest OS导致不可接受的改变。因此我们避免了和使用影子页表相关的开销和额外的复杂度 — Xen中的方法是直接地由MMU记录guest OS的页表,并且限制住guest OS只能做读访问。页表更新通过hypercall传递给Xen;更新请求在被采纳以前经过确认,这么做就确保了安全性。

    为了有助于确认,我们给机器的每个页框都建立了一个相关的类型和引用数。一个页框在任何时候都会排它地具有下述的某一个类型:页目录(PD),页表(PT),局部描述符表(LDT),全局描述符表(GDT)。同时,这个页框还可能是可写(RW)的类型。一个guest OS可以为它自己所属的页框创建可读的映射,而不必理会页框的当前类型。一个页框只有在它的引用数为0的时候,才能被安全地重新分配给其它任务使用。这个机制被用于满足系统对安全性一贯的需求;例如,一个domain不能够任意地对页表的某个部分建立可写的映射,如果要这么做的话就必须要求页框同时具有PT和RW类型(//什么情况下是可读的映射?什么情况下又是可写的映射呢?)。

    类型系统还要被用于跟踪那些用于页表的页框中哪些是已经被确认过的(//页框用于页表,即页内容填入页框)。这时,guest OS要指出页框是否被分配用作页表 — 这就需要在页框的类型被定为PD或者PT后(//说明页框是用于页表的),由Xen对页框中的每一项做一次性地确认,直至后来由guest OS发出释放(unpin)的请求(//由guest OS释放页框)。这在改变页表基指针的时候是很有用的,因为它不需要在每一次上下文切换时都对新页表进行确认(//因为现在只确认页框了)。注意,一个页框在被释放并且引用数为0之前是不能够被重新分配给其它任务的,这样就避免了guest OS可能会绕开引用数机制而直接利用释放请求导致的危险。

    为了减少所需的hypercall调用的次数,guest OS能够在利用一个hypercall进行整批处理之前在局部将更新排入一个队列。特别是在创建新的地址空间的时候,这一点是尤其有好处的。但是无论怎样,我们必须确保更新被提交得足够早以保证准确性。幸运的是,一个guest OS在第一次使用一个新的映射前要执行一次TLB刷新:这确保了任何被缓存的改变(//这些改变目前仅存于TLB中,还没有被写入内存页表项)都是没有经过确认的。因此,在TLB刷新之前立即提交那些待处理的更新就可以满足正确性(//更新的时间,解决了什么时候进行成批更新操作以保证正确性的问题)。可是,有一些guest OS会在TLB中没有陈旧表项存在(//没有陈旧表项意味着更新都已经送达内存中?)的时候省略掉这个刷新的步骤。在这种情况下,就有可能发生第一次试图使用新的映射时会发生缺页错误(//因为没有刷新TLB)。 这时,guest OS错误句柄就必须要核查是否需要更新;如果需要的话,TLB就要被刷新(//加入所缺的内容),并且将导致刚才缺页错误的指令重新执行。

    3.3.4物理内存

    为各个domain进行的初始的内存分配,或者说内存保留,都是在domain被创建的时候进行的;因此,内存在domain之间是静态划分的,这就提供了强大的隔离性。最大允许的内存保留量是被规定了的:如果某个domain中的内存压力增加了,那么它就可以从Xen争取额外的内存页,直到达到规定保留量的上限。反过来,如果一个domain希望节省些资源,避免不必要的开销,它也能够通过释放内存页给Xen来减少它的内存保留量。

    XenoLinux实现了一个气球驱动 [42](//没看相关文献),它能够通过在Xen和XenoLinux的页面分配器之间传递内存页来调整domain的内存使用。虽然我们能够直接修改Linux的内存管理例程,但是气球驱动能够利用现有的操作系统功能来进行调整,因此简化了Linux的移植工作。无论怎样,准虚拟化能够被用于扩展气球驱动的能力。例如,guest OS中的内存越界处理机制能够被修改为通过向Xen请求更多的内存页来自动地减轻内存压力。

    大部分操作系统都假定内存空间是由大量的较大规模的连续区域组成的。由于Xen并不保证它为guest OS分配的内存区域是连续的,所以guest OS需要为它们自己创建连续的物理内存的假象,即使它们实际在底层分配到的硬件内存是稀疏的。guest OS通过简单地维护一个以实际分得的页框号为索引的数组,来完全负责从实际分得的地址(physical)到硬件地址的映射。Xen提供了一个共享的地址转换数组,这个数组用于支持从硬件地址到各个domain实际分得地址的映射,它是所有的domain都可读的 — 更新这个数组是经过Xen确认的,以确保guest OS能够拥有相应的硬件页框。

    即使一个guest OS在大多数情况下选择了忽略硬件地址(//因为guest OS喜欢在连续的地址空间上运行),但是在它访问它所拥有的页表的时候(这时必须使用硬件地址)必须使用转换表。硬件地址也可以暴露给操作系统存储管理系统中的有限的某些部分以优化存储访问(//具体是哪些部分可以直接“看到”硬件地址呢?)。例如,一个guest OS可以分配特定的硬件页用于优化以实际分得地址为索引的缓存中的布局,或者使用超级页将硬件内存中的连续部分作自然对齐的映射。

    3.3.5网络

    Xen提供了虚拟防火墙—器(VFR)的抽象,每个domain都有一个或多个在逻辑上附属于VFR的网络接口(VIF)。VIF看上去有些现代的网卡:具有两个I/O缓冲区描述符环,一个用于发送一个用于接收。在每个方向(//发送或者接收)上都有一些相关的规则形式(<模式>,<动作>)— 如果模式(pattern)匹配上的话,那么相关的动作(action)就会被起用。

    Domain 0负责插入和删除规则。例如在典型的情况下,可以增加规则防止源IP地址欺骗,或者增加规则确保基于目的IP地址和端口的正确的数据分派(demultiplexing)。规则也可以是和VFR上的硬件接口相关的。特别是我们增加的那些用于执行传统的防火墙功能的规则,比如防止在不安全的端口上建立连接的企图。

为了发送一个数据包,guest OS简单地将缓冲区描述符排队进发送环中。Xen复制描述符,同时为了确保安全性,还要复制数据包头并执行匹配过滤规则。数据包的有效载荷不会被复制,因为我们使用的是分散—集中式(scatter-gather)的DMA;这里要注意的是,相应的页框必须被绑定,直到数据包传送完成。为了保证公平性,Xen在数据包调度器上实现了简单的循环轮转(round-robin)算法。

    为了有效地实现数据包的接收,我们需要guest OS为每一个它接收到的数据包一个没有使用的页框(//这个招儿挺绝的,我就不将页内容复制到我自己的页框里了,直接把这个页框纳入自己的旗下,然后再换个我没用的空页框给你,反正只要修改地址转换数组就可以了);这就避免了需要在Xen和guest OS之间复制数据包内容的麻烦,但是这么做必须要求在网络接口中接收缓冲队列中的有页对齐的区域(//因为这么做是直接以页框为单位进行的,所以一次就是一页的内容,所以需要提供页对齐的缓冲区域才可以进行)。当一个数据包被接收,Xen立即检查接收规则组来确定目的VIF,然后将数据包缓冲区和相应的接收环(//接收环存在于各个domain中)交换一个页框。如果这时没有页框可用的话,数据包就被丢弃。

    3.3.6 磁盘

    只有Domain 0能够不经检查地直接访问物理(IDE和SCSI)磁盘。所有其它的domain访问永久性存储介质的时候,都要通过虚拟块设备(VBD)抽象。这个抽象是由运行在Domain 0中的管理软件来创建和配置的。由Domain 0管理VBD使得Xen中的机制比较简单,不避使用更复杂的解决方案(比如Exokernel中使用的UDF[23])。

    一个VBD是由一些和所有权以及访问控制信息相关的扩展组成的,可以通过I/O环机制来访问。一个典型的guest OS磁盘调度算法将重新排定请求的优先级并把它们排进环中,这样做是为了尽量减少响应时间,并且可以有区别地进行服务(例如,由于进行投机的向前读请求的代价很高,调度器可能会选择主动先去调度后面的对同步数据的访问请求)。另外,因为Xen对真实的磁盘规划具有更完整的认识,所以我们也要在Xen中支持重新定序(//刚刚提到的是guest OS),并且可以乱序地返回响应。因此,对于guest OS来说,VBD有一点像SCSI磁盘。

    在hypervisor内部还为每个VBD维护了一个转换表;整个表中的内容都由Domain 0通过特权控制接口进行安装和管理。在接收到一个磁盘请求后,Xen检查VBD标识符和偏移,并且产生相应的扇区地址和所属物理设备。许可检查也是在这个时候进行的(//检查到底能不能进行这个磁盘操作)。零复制数据传递将以DMA的方式在磁盘和绑定到该发出请求的domain上的内存页之间进行。

    Xen会使用简单的循环轮转方式来成批处理各个存在竞争关系的domain发出的请求;然后,在到达磁盘硬件之前,这些请求传给标准的电梯调度器。domain可以显式地设置重定序障碍(//不许重定序)来防止在必须维持高层次语义的时候(例如,在使用了一个预写日志(write-ahead log)的时候)进行重定序。当成批的请求中能够显现出访问的公平性的时候,低层的调度能够给我们带来很好的吞吐量。下一步工作将研究使用现有的技术和调度器提供更可预测的隔离性和支持更有差别的设备。

    3.4建立新的Domain

    为一个新的domain建立初始的guest OS结构,这个任务很大程度上是委托给Domain 0完成的。Domain 0使用它的特权控制接口(2.3段)访问新的domain的存储空间并告知Xen该新domain的初始寄存器状态。这个方法相对于由Xen建立整个domain来说有一些优势,包括减少了hypervisor的复杂度,改进了鲁棒性(对特权接口的访问要经过完全地检查的,使得我们能够在初始阶段捕捉到大部分的bug.

    最重要的是,整个建立过程易于被扩展,可以应付新的guest OS.例如,Linux内核引导时的地址空间是要比Windows XP简单得多的。我们可以为所有的guest OS指定一个固定的初始内存规划,但是这样的话就需要针对每个guest OS编写额外的引导陷阱代码用来安置操作系统所需的其它部分。不幸的是,这类代码是非常难以实现的;为了获得简单性和鲁棒性,更好的实现方法就是使用Domain 0,它能够提供比引导程序更充裕的诊断和调试支持。

    Scatter-gather DMA方式是与block DMA方式相对应的一种DMA方式。

    在DMA传输数据的过程中,要求源物理地址和目标物理地址必须是连续的。但是在某些计算机体系中,如IA架构,连续的存储器地址在物理上不一定是连续的,所以DMA传输要分成多次完成。

    如果在传输完一块物理上连续的数据后引起一次中断,然后再由主机进行下一块物理上连续的数据传输,那么这种方式就为block DMA方式。Scatter-gather DMA方式则不同,它使用一个链表描述物理上不连续的存储空间,然后把链表首地址告诉DMA master.DMA master在传输完一块物理连续的数据后,不用发起中断,而是根据链表来传输下一块物理上连续的数据,直到传输完毕后再发起一次中断。

    很显然,scatter-gather DMA方式比block DMA方式效率高。

    4.相关工作

    虚拟化技术被应用在商业化和研究型操作系统上已经有近30年了。IBM VM/370[19,38]最先使用了虚拟化技术以提供对先前存留的代码的支持。VMware[10]和Connectix[8]采用了将常用的PC硬件进行虚拟化的方法,允许多个操作系统在同一台主机上运行。所有这些例子都对底层硬件(至少是底层硬件的一个子集)进行了完全虚拟化的实现,而并非是准虚拟化的方法提供给guest OS一个修改后的接口。正如我们的评估结果中给出的:完全虚拟化虽然能够更容易地支持商业市售的操作系统,但是却大大降低了性能。

    VMM方法还被Disco用于将常用的操作系统高效地运行在ccNUMA机器上[7,18].其间要对被操控的操作系统做少量的改动,以使其能够虚拟化地运行在MIPS体系结构上。另外,出于性能的考虑,还要做一些其它修改。

    现在,我们知道有两个其它的系统也采用了准虚拟化的方法:IBM不久前提出的Linux的准虚拟化版本允许大量的Linux实例同时运行,将用于他们的zSeries大型机上。Denali[44]在之前已经讨论过,它是一个暂时隔离的内核,试图提供能够操控大量虚拟操作系统实例的系统能力。

    除了Denali,我们还知道有两种其它的方法使用了低层虚拟化技术建立分布式系统的底层架构。vMatrix[1]是基于VMware的,它的目标是建立一个用于在不同机器间移动代码的平台。由于vMatrix是在VMware之上开发的,因此它更关注的是虚拟化技术在分布式环境中存在的高层问题。另外,在IBM提出的“托管管理(Managed Hosting)”服务中,虚拟Linux的实例可以在IBM大型机上被租用(//大型机上跑多个Linux实例,你可以租一个用,搭建你自己的系统,和其他租户共享大型机的资源)。

    PlanetLab项目[33]构建了一个分布式的底层架构,它的设计目的是作为实验床用于研究和开发地理空间分布的网络服务。平台的对象是研究者,试图将单个的物理主机划分为条(sliver),提供同时的对用户的低层访问。项目当前使用的是VServers[17]和SILK[4]来管理操作系统内部的共享。

    我们再和操作系统外延研究和主动网络通信研究中的一些思路作比较。当代码在Xen上面运行的时候没有必要检查其“安全性”,也没有必要去检查代码运行是否能够保证终止,因为在这些情况中唯一的受害人是那些可疑的客户。于是Xen提供了更通用的方案:这个方案不需要由一个可信的编译器为被操控的代码做数字签名(比如SPIN[5]),不需要这些代码被一个安全证明伴随(比如PCC[31]),不需要由一种特殊的语言写成(比如SafetyNet[22]或者其它基于的系统),也不需要依赖于特殊的中间件(比如移动代理(mobile-agent)系统)。当然,这些其它的技术能够继续在运行在Xen上的guest OS中使用,而且可能会对那些时限更短暂的任务负载有着特别的用途,因为这类任务没有机会被成批处理以减少启动一个新的domain的代价。(//这段的意思,我的感觉是在操作系统外延研究和主动网络通信研究为了保证代码安全,采用了多种多样的方法;但是在Xen中,这些方法都是不必要的,因为Xen的安全性确认策略比较简单,前文有提及;但是这些方法在Xen中也还是有它们的作用,比如对于时限短暂的任务,它等不及成批地被确认,那么它就需要用其它方法保证安全性。)

      关于语言级虚拟机(//比如虚拟机)方法中也存在着类似的问题:一个管理资源(resource-managed)的JVM[9]肯定能够操控不可信的应用,前提是这些应用必须被编译为Java字节码并且遵循特别的系统安全模型(//不可信的代码,即使出了问题,但是由于其遵循系统安全模型,所以也不会造成危害)。这样的话,Xen就能够容易地支持语言级虚拟机,就像支持其它运行在guest

    OS上的应用一样。(//这段的意思,和前面类似,仍旧是表明Xen并不提供过多的安全性检查;如果要跑语言虚拟机之类的应用,语言的安全性要由虚拟机应用本身保证,而不关系到Xen.)

    5.讨论和结论

    我们在上文介绍了Xen hypervisor.它能够将计算机的资源划分给各个运行着guest

    OS的domain.我们的准虚拟化设计特别强调了性能和资源管理。我们还描述和评估了XeonLinux,XeonLinux是将Linux 2.4内核向Xen上做的完全移植。

    5.1 Future Work — 将来的工作

    我们认为Xen和XenoLinux完全能够被用于更广阔的空间,所以我们准备在不久的将来把我们的软件做成一个公开版本。当前已经有一个Beta版本正在被评估(//貌似就是那个Clarkson University做的工作);一旦评估阶段结束,我们就会在项目主页上发布1.0版。

    在完成初始版本后,我们计划对Xen做一些的扩展和改进。为了增加虚拟块设备的效率,我们准备实现一个由块内容索引的共享的通用缓冲Cache(universal buffer cache)。这将为我们的设计增加受控的数据共享,同时却不牺牲隔离性。为虚拟块设备增加写复制(copy-on-write)语义,使它们能够在domain之间被安全地共享,即使是不同的文件系统也不会有问题(//写复制,保证一致性,减少内容复制开销;不过跨文件系统应该还是不很容易吧?)。

    为了提供更好的physical(//物理?还是像之前提到的是“实际分得的”?应该是后者)内存性能,我们计划实现一个最后机会页缓存(LPC:last-chance page cache)。这是一个全系统范围内的空闲页链表,只有在机器内存未被分光的情况下,链表才有非零的长度。当guest OS虚拟存储系统选择舍弃一个干净(clean:数据中没有dirty data,都是与磁盘中相同的)的页时会使用到LPC;这个干净的页会被加入到空闲链表的结尾,而并非被完全抛弃。如果在该页重新被Xen分配之前发生了和该页相关的错误,那么对错误的处理是不需要磁盘访问的(我的理解是,以往的方法如果操作系统释放了内存资源的话,那么它如果再想使用刚才释放页上的资源就必须重新从磁盘上调入;而现在的last-chance,就给了操作系统一个机会,如果出现了和刚释放掉的页内容相关的错误,那么操作系统可以直接从这个LPC中调相关页,而不用访问磁盘)。

    Xen的一个重要角色是作为XenoServer的基础。XenoServer的设计目标超越了单机的范畴,它要搭建的是支持一个规模计算架构所必需的控制系统。对于我们的设计来说,关键在于资源的使用要被精确地计算并且由工作的发起者想办法满足资源需求 — 如果资源必须要及时兑现,我们就使用一个拥塞定价策略来处理那些超过资源提供能力的要求,使用透支的方法满足超出的需求。这就必须要有精确、及时的I/O调度,它要能够更有弹性地处理那些不友好(//恶意透支?)的工作负载。我们还计划创建虚拟块设备租借等形式,将会计学中的一些理论(//上述的租借,透支之类的概念都是属于会计学的范畴)借鉴进我们的块存储架构中。

    为了能够为XenoServer的管理和经营提供更好的支持,我们正在加入对日志审核和日志鉴证更彻底的支持。我们还在开发其它的VFR规则,希望这些规则能够使我们检测和防止更大范围的对社会有危害的网络行为。最终,我们正在继续我们在XenoXP上的工作,最重要的工作就是编写网络和块设备驱动实例,工作的目标是完全支持企业级的服务器应用(如IIS)。

    5.2结论

    Xen提供了一个优秀的平台,在这个平台上能够配置广泛的多样化的以网络为中心的服务,比如动态web内容的局部镜像,媒体流的编码转换和分发,多用户游戏和虚拟现实服务器,还有为瞬时连接设备提供短暂网络连接的“智能代理”[2]服务。

    Xen直接解决的是在部署服务时遇到的最大障碍,即当前不能够在低实例化开销的前提下,对瞬时服务器操控较短的时间(//瞬时服务器:时有时无,有时候需要有时候不需要;而即使是每次需要,也只是操作很短的时间,马上就又不需要了;所以这样的话,频频切换,就需要很大的实例化开销,因为每次启动瞬时服务,就要实例化一次;但是Xen中,反正我可以跑多个系统,那就专门留一个或几个系统给你跑瞬时服务,同时还不耽误我其它服务的性能)。通过允许100个操作系统运行在单台服务器上,我们减少了两个数量级的相关开销。更进一步的,我们可以把对每个操作系统进行设定和配置的过程转变为软件行为,这样就能够更容易地操控更细粒度的时间片。

    正如我们诘?部分给出的实验结果,在Xen上运行XenoLinux的性能几乎与本地Linux系统的性能相同。之所以会有这样的结果,主要得益于对两个部件之间接口(//就是VMM吧?操作系统和底层硬件两个部分之间的接口)的细致设计,这使得我们几乎感觉不到在使用资源管理工具时带来的开销。我们的下一步工作是移植BSD和Windows

    XP的内核到Xen上来验证Xen提供的接口的普适性。

阅读(632) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~