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可能会绕开引用数机制而直接利用释放请求导致的危险。
最新相关文章
发表评论