对操作系统虚拟化的一些总结

CPU如何实现虚拟化?
在现代计算机操作系统上,CPU被切割成了时间片进行虚拟,进行分配的,而且CPU本身被切割成了时间片,在各个进程之间进行分配的。那么就可以把CPU切割一个一个时间片,在各虚拟机之间进行分配。

CPU虚拟化遇到的难题:
1.在虚拟机上面申请内存的时候,只能去物理机上的内存申请
2.不能让虚拟机的内核去执行CPU的特权指令。
CPU是分成环的,CPU是一个硬件芯片,这个芯片有自己的微码编程接口,微码编程接口说白了就是利用CPU内置的在硬件制造时所生成的逻辑上所能够支持的运算方式,或者叫运算命令。这些命令就是在某个针角上发送什么信号来控制CPU可以做什么样的事情。CPU中的某些指令是可以直接控制资源的,有些命令是直接计算的。所以CPU指令是分集的,分为普通指令和特权指令。x86系列的CPU就根据内部所谓分成的环,来区别指令所在的位置。CPU分成4个环,分别是环0,环1,环2,环3来区分各个指令所能运行的位置。环0被称为特权环,里面放的都是特权指令,是操作系统才有权限去操作的;环1,环2上也都有写一些指令,只不过它们的敏感级别是逐渐降低的;环3是级别最低的环,是普通指令可以去操作的。为什么我们的操作系统可以控制CPU?因为操作系统负责去运行这些特权环中的指令,而普通进程只能运行这些环3中的指令。现在在x86系列的CPU系统中的确有4个环,但是环1和环2是未使用的。

虚拟机中的CPU是通过软件模拟出来的,虚拟机中的CPU想要真正的跑起来,还必须转换到真正的CPU中去运行指令。其实虚拟机中内核就算在CPU中运行的时候,只要不是特权指令,哪怕它真正运行中宿主机的CPU上,也是没有问题的。因此虚拟机软件可以监控每一个虚拟机中的内核打算运行的指令是什么,如果发现是一个非特权指令,就由虚拟机软件直接调度到硬件中去执行;如果发现是一个特权指令,虚拟机可以告诉他没有这个指令,因此可以截住这个特权指令。截住以后它实现在VMM级别上做成相应的只针对这一个虚拟机的操作。最终转换的结果依然是只让这个VMM来控制住了这一组模拟硬件的操作。所以我们是不能让这些虚拟机运行在特权环中,并且还不能让他知道,因此靠模拟的方式给虚拟机营造一个假的特权环。

但是对于x86的CPU来说,有一个巨大的问题,它有一些敏感指令属于特权指令,但是进程是可以直接访问的,因此x86系列的CPU天生就不适合做虚拟化。所以VMM不仅需要监控特权环,还需要监控非特权环中的那些敏感指令。但是VMM本身并不具备使用特权指令,因此VMM还需要像宿主机申请,只有宿主机通过,才能运行。

内存如何实现虚拟化?
CPU中有MMU,每一个进程运行的时候看到的是线性地址,不是物理地址。那么虚拟机中的进程获取内存的时候,首先会通过虚拟机的MMU转化成物理机的虚拟地址,然后通过物理机的MMU转化成物理机的物理地址。由于内存本身就是虚拟化的,所以内存虚拟化可能会进行两次MMU转换,造成性能的底下。并且这不是最严重的情况,我们知道从虚拟地址转换成物理地址的时候会借助TLB缓存,所以有可能出现的情况就是多台虚拟机的虚拟地址转换成物理地址时候的TLB可能会在物理机中的虚拟地址中命中相同,造成混论。所以默认的策略是每次在虚拟机之间进行切换的时候必须清空TLB,所以这种情况下TLB带来的性能几乎为0。所以为了解决这个问题,只能在硬件级别提供解决方案了。因此在CPU的内部对MMU做了虚拟化,GuestOs在将自己的VA转化为PA的时候,同时也借助于虚拟化出来的MMU把VA转换成HA。把VA转换成HA的结果就是可以直接从HA取数据,就不再需要借助于VMM把PA转换为HA了。这个MMU叫做影子MMU(shadow MMU)。但是这样仍然不能解决TLB缓存的命中问题,所以解决的方案是在每一个GuestOs打个标记,每次TLB去查找对应GuestOs中的TLB缓存的时候,都会带上该GuestOs的tag标记来避免TLB的缓存问题。这种叫做打了标签的TLB,并且也只有你的CPU支持这种打标记的功能才能够增加TLB的缓存率。专业的支持硬件虚拟化的CPU通常都支持该功能。shadow MMU在Inter中的实现叫做EPT,在AMD上的叫做NPT

当虚拟机上需要打开一个大的文件的时候需要申请更多的内存,它需要像自己的内核申请,这个内核就尝试的指挥CPU去分配内存。但是要指挥CPU去分配内存是属于特权指令的,需要被VMM捕获,并由VMM代为像宿主机的内核申请。由宿主机在真正的物理内存中找到一个页面返回给VMM,再由VMM返回给虚拟机。虚拟机拿到这段内存以后,就要把这段内存映射给真正发起这个进程的线性地址空间,这个进程的线性地址空间的物理空间其实是物理地址的虚拟地址空间,最终还要映射成真正的物理地址空间。并且两次映射的地址空间是不一样的


磁盘IO如何实现虚拟化?
硬盘只有1个,有那么多虚拟机,如何给每个虚拟机一个硬盘呢?在vmware中,通过磁盘映像文件,本地回环设备来实现。回环设备可以以稀疏的磁盘方式呈现。所谓稀疏的磁盘方式就是告诉别人自己有多大的文件,但是其实是没有的。于是宿主机就可以告诉虚拟机有一块硬盘可以用,可以格式化,可以分区等,但是实际上是没有这块硬盘的。这块硬盘最终还是要转化为真正存数据的地方去的。它还是要转换到真正的磁盘的某个分区上的某个文件中去。所以虚拟机的某个进程需要访问文件的时候,它要通过IO调用放在自己假的磁盘上,而这个磁盘最终还要通过真正的IO调用放在真正的磁盘上去。如果有多个虚拟机,都频繁的往磁盘上写数据,那么最终它们都要合并成真正的磁盘IO。所以如果物理机的磁盘IO性能很差的话,虚拟机的性能必然也会很差。虚拟机也可以直接使用硬件的,可以把一块物理硬盘多划分成几个分区,把其中的一个分区直接映射给VMM使用。这样就可以直接在硬盘上使用,而不用使用hosted做中转,这种叫做透传技术。这个时候虚拟机的IO就直接在宿主机的硬盘中去了,但是这些IO需要通过VMM的监控。

网络IO如何实现虚拟化?
在虚拟机中要由软件的方式模拟一个网卡出来。虚拟机中的网络最终需要通过物理家的网卡进行转发。

IO虚拟化实现的难题:
1.物理机的网卡和虚拟机的网卡之间是怎么通信的呢?
这是借助于VMM来实现的。VMM在宿主机上用软件的方式模拟出来了一个交换机。

2.外部的主机访问物理机和虚拟机的时候,怎么能够把报文发送到正确的地址?
首先来考虑一下这个问题。外部的主机发送一个报文去访问虚拟机的时候,只有通过物理机的网卡才行。而物理机的mac地址和虚拟机的mac地址是不一样,按照正常的情况来说,物理机的网卡是不应该接受发送到虚拟机的网卡的。那么虚拟机又是如何接受到报文的呢?这里需要把物理机的网卡做成混杂模式,不管目标mac是否是它都可以接受;其次把这块网卡做成交换机,模拟成一个硬件交换机接口,而后在物理机内部再虚拟出一块网卡只给当前物理机使用,而原来网卡的mac地址就绑定在这个虚拟给host主机的虚拟网卡上了。所有,只要能够发到这块交换机上来的报文,都可以找到实际主机或者虚拟机的MAC地址。

虚拟化的类别:
1.半虚拟化:
所谓半虚拟化就是运行在硬件上的一个VMM,并且不需要hosted的支持。VMM必须运行在Ring 0上,同时为了避免GuestOs控制系统资源,GuestOs不得不降低自身的运行级别而运行于Ring 3上。我们让GuestOs明确知道自己运行在虚拟机环境中,它知道自己不具备运行特权指令,一旦需要运行特权指令,它就自动的通过一个接口给VMM打交道。这样就不需要VMM去捕获了,因为捕获本身需要监控,监控就需要浪费资源。因此这样一来,就需要改GuestOs的内核了,让内核明确知道自己运行在虚拟机环境中,也知道自己对那些特权指令是没有权限执行的,如果需要执行,它自己就把这个特权指令的执行操作转换成对VMM中某个功能的调用。而VMM为了实现这个功能,它也直接把对这些特权命令的执行做了一些接口。如果某个虚拟机需要使用特权指令,就直接调用这些接口,在这些接口上能够转换成安全的方式执行。从而,虚拟机上的OS就知道自己运行在虚拟机环境中了。像这种方式,VMM将自己所提供的特权指令通过接口输出给虚拟机啊,由虚拟机内核直接进行交互的机制,可以理解为para-virualization(半虚拟化)。这种VMM通过把自己的特权指令通过接口给GuestOs调用的方式叫做hypercall。windows不能运行在这种环境下(原因你懂的)。

2.硬件虚拟化:
对于CPU来说有特权指令集的,对于CPU来说分成了4个环,分别是环0,环1,环2,环3。由于VMM运行在Ring 0上,所以把GuestOs挤出了Ring 0。被挤出了Ring 0以后,就只能对CPU进行模拟或者采用半虚拟化技术,这种叫做特权级压缩。而硬件虚拟化就是指在CPU的最内部多加了一个环,这个环称为-1环。这样一来VMM运行在Ring -1上,GuestOs运行在Ring 0上。这种情况下,Ring -1环变成了特权环,Ring 0环变成了正常环,0环无法执行特权指令,-1环可以运行特权指令。这样就让各个GuestOs的内核可以运行在Ring 0上,所以基于这种方式,就算我们使用了虚拟化技术,而这种虚拟化技术没有使用半虚拟化,我们仍然可以在虚拟化环境中装GuestOs,而且对它内核不加任何修改。如果GuestOs需要执行特权指令,仍然需要VMM将其完成转换。基于这种技术带来的好处是:一.我们不需要通过软件的方式模拟出一个特权指令集给GuestOs了,因为GuestOs自己有Ring 0了;二.这样并不意味GuestOs就可以运行特权指令了,VMM不过工作在Ring -1上监控各GuestOs对特权指令的执行,这样就意味着对特权指令的执行GuestOs仍然没有权限执行,仍然需要VMM的参与。这种情况下,就不再需要修改内核,不再需要提供专门的模拟,在CPU的硬件级别,它就能够捕获各GuestOs对特权指令的请求。所以这种性能有一定的提升,但是对于半虚拟化来说,这种的提升仍然是有限的。硬件虚拟化也叫做HVM(Hardware assistant VM)。在实现的硬件虚拟化的技术中,Inter和AMD各有解决方案。Inter的技术叫VT-x,ADM的叫做ADM-V

IO虚拟化的类别:
1.完全虚拟化
2.半虚拟化(在guestOs的磁盘IO和网络IO中装fronted驱动)
3.透传技术(IO-through)
我们知道在操作系统开机的时候,每一个io设备都会像cpu申请一些列的随机端口,这种端口叫做io端口;正是这些io端口的存在,cpu才可以与io设备进行读写交互的过程。但是GuestOs在启动的时候也会申请一些IO端口,GuestOs申请的端口和物理机的IO端口是不一样的,因此为了完成彼此之间的映射关系,就需要通过IOMMU把GuestOs中的IO端口直接映射成物理机中的IO端口。因此Inter率先实现了这种IO硬件虚拟化技术,叫做IOMMU。

你可能感兴趣的:(linux)