vmware启动的时候同时会有一个vmware-vmx启动,二者通过pipe或者socket通信,实际上,vmware只是一个输入/显示客户端,类似X服务器,它一般在一个窗口中运行一个虚拟操作系统。真正工作的是vmware-vmx这个进程,它和内核中monitor通信完成虚拟操作系统的执行和数据向vmware的传导和接收,通信的接口是/dev/vmmon字符设备,使用最多的就是其ioctl例程。
     执行32位保护模式虚拟操作系统的虚拟机实现中最复杂的不是别的,正是虚拟OS名字中所体现的,它便是内存的保护,在运行在真实硬件上的操作系统上,它是由MMU实现的,而在虚拟机中,guest os上的进程的线性地址必然要转化为真实机器上的物理地址才可以,而这个转化并不能直接进行,因为guest os并不知道自己在虚拟机中运行,所以guest进程必然还是首先使用它自己的guest os的mmu机制来转化,现在问题就是如何将这个guest os的mmu和真实机器的mmu联系起来。vmware使用了所谓的影子页表的方式实现,其实这个影子页表只是一个转化后的结果,转化分为两步,第一步是guest的线性地址转化为guest的物理地址,第二步是guest的物理地址转化为host的真实物理地址,这里有趣的事就来了。
     我们的虚拟机建立好以后,需要配置一下物理内存的大小,然后启动它以后会在目录下创建一个扩展名为.vmem的文件,其大小和你配置的物理内存的大小是一样的,这个文件将要映射到真实机器的内存当中,大小正好是虚拟机的“物理内存”大小,它是一个文件,是平坦的,然而它在内核真正需要的时候,其映射的物理内存却不一定是连续的,而可能是分离的页面,正是这些分离的不连续的页面提供给虚拟机一个连续的“物理内存”的印象,虚拟机中的“物理内存”就是这些不连续真实主机操作系统的页面。然而这是怎么做到的呢?想想也不难,任何现代的操作系统,不管是运行于虚拟机还是运行于真实机器,其对内存的访问都是要通过mmu的,这些操作系统所访问的都是虚拟地址,就连内核空间也不例外,也就是只要mmu能为这些虚拟地址映射到一个真实的物理页面,就算物理页面不连续也无所谓。理解这一点的时候,千万不要为linux内核内存的一一线性映射给迷惑了,倒是linux高端内存的映射方式是一种理解虚拟机“物理内存”的一种媒介。
     有了以上的理论,下面要做的就是影子页表的实现了,这也不难,就是虽然当前运行的是虚拟机上的操作系统,然而其MMU操作还是要在真实机器中完成,也就是说,真实的机器内核空间运行着一个VMM的monitor程序,由它来提供虚拟机操作系统的所有的页表映射,也就是提供虚拟机操作系统运行所需的cr3寄存器的物理地址,这个物理地址指向的就是影子页表。
     那么,如果vmm运行在ring0,而guest os的内核也运行在ring0,怎么能保证不混乱呢?办法就是让guest os内核运行在ring1,但是这样的话,guest os的用户进程执行了一个int X指令,由于int是陷入到ring0的指令,guest os怎么能收到并且提供系统调用服务呢?ring 0的vmm即使收到,又如何转发给运行于ring1的guest os让其自由处理呢?由是,我们不妨先按照自己的想法想一下如何实现,然后将已有的虚拟机实现往我们自己的实现上套,这样就不至于一开始就迷失于各个虚拟机复杂的文档和源码了。
     那么虚拟机上的进程是如何工作的呢?如果知道了这个,虚拟机的运行方式也就知道了,然而最关键的就是它体现的是最复杂部分的实现,这个最复杂的部分就是内存虚拟化。
     理解软件或者和硬件配合的软件如操作系统这种东西的最佳方式就是设想一个场景,如果这个场景被你相通了,内中各个步骤关节都被你搞明白了,那么你也就掌握了最关键的大局,接下来你再去看什么文档源码之类的东西,总之这种情景分析十分有效,起码对我十分有效。下面就以guest os上的fork为例来看一下怎么执行,选用fork是因为它有递归的性质,任何的新的进程在linux中都是被fork出来的,相反,如果选用read/write之类的就会把事情搞复杂,因为后者会涉及到虚拟化的另一个大的主题-IO虚拟化。guset os运行了linux,假定guest os上当前的一个进程的影子页表已经存在了,它fork一个子进程的时候将会创建另一个影子页表-有点数学归纳法的意思哦,过程如下:
1.fork为系统调用,本该陷入guest os的运行与ring1的内核,可是int指令却陷入了ring0的vmm;
2.vmm和guest os共享一部分内存,它既是host os中的一个内核执行绪,又可以被guest os触碰,它截获int指令,将之路由给guest os;
3.guest os接管这个int,发现要创造一个新的进程,于是创建页表:
3.1.在普通的host上的linux,不考虑高端内存的话,物理内存和虚拟内存是一一映射的,内核操作的也是虚拟地址,它们对应的物理地址连续是因为linux的实现就是这样,如果换成windows,就不是这样了,内核中不也有分页内存吗?
3.2.在虚拟机上的guest linux,它的运行并不依赖物理内存(前面说过,现代操作系统看到的都是虚拟内存地址,物理内存仅仅是一种资源),因此它所关心的就是有个机制能将现在要操作的虚拟地址转成物理地址就可以了,这是由mmu来完成的,已经比操作系统低了一个层次了,在mmu看来,它才不知道你运行的是windows还是mac os呢。
3.3.mmu其实并不属于操作系统的范畴,然后操作系统却需要管理各个页表,而页表却是mmu操作的对象,由于mmu的工作完全在运行于ring0的vmm中完成,因此cr3的物理地址也是由vmm指定的,由于vmm可以看到所有的物理内存,因此它能完成这个工作。
3.4.guest os上的当前进程的页表由当前vmm中的cr3-也就是整个系统中的cr3指定,又由于guest os已经陷入了内核态,内核态的页表又都相同,因此vmm当然能找到guest os的当前调用fork的进程在创建子进程页表时需要访问的虚拟地址所对应的物理页面,这个页面肯定属于.vmem文件所映射进内存的页面,然而它只是映射进了内存,不一定被分配了物理页面啊
3.4.1.如果没有被分配物理页面,也即是页表本身缺页,那么缺页中断将被触发,那么分配一个页面,映射进该地址,也就是为guest os补全了一个页面的物理地址,毕竟虚拟内存需要的页面最终是需要在物理内存中分配的。
3.4.1.1.在guest os的alloc_page中操作的都是虚拟地址,然而内核却需要管理整个物理内存,这个物理内存本身的管理需要的也是虚拟地址,这个只要在vmm管理的影子页表中有映射即可。
3.4.1.2.比如guest os内核中的前三个物理页面的起始物理地址肯定为0,4096,8192,起始虚拟地址则是(3G+page数组+0),(3G+page数组+4096),(3G+page数组+8192),如果运行在host os中这三个地址的虚拟地址就是这三个数,而对应的物理地址则是前三个数,然而在guest os中,前三个页面的虚拟地址对应的仍然是那三个数,只是物理地址对应的则不一定是那前三个数了,而可能会是任意的数,但是这个有关系吗?没有关系,因为我们运行的是现代操作系统。
3.4.1.3.guest os在初始化的时候,已经将自己内核的虚拟地址按照操作系统特定的方式全部映射到.vmem文件中了,比如对于linux就是一一线性映射,同时vmm也构建好了影子页表,内存中有一个.vmem文件大小的连续虚拟地址空间,然而可能还没有被分配物理页面,vmm需要做的就是当guest os需要访问这个虚拟的.vmem文件映射空间的时候为其提交物理页面,并且用这个物理页面的物理地址来构造影子页表而不是用guest os在.vmem文件中的它看到的物理页面的地址来构造页表。
3.4.1.4.再次重申,现代操作系统看到的都是虚拟地址。仅在它管理mmu的时候需要页面的物理地址。
3.4.2.如果已经有了物理页面,则guest os继续。
4.5.如是,子进程的页表被构建完毕。
4.6.guest os的进程切换,完全按照guest os的方式进行,最后切换cr3,然而就在这时,事情发生了
4.6.1.由于切换cr3的时候需要的参数是页目录的物理地址,但是guest os看不到物理地址,mmu是在host os中的vmm中被管理的,这怎么办?
4.6.2.vmware使用了BT技术,也就是二进制翻译技术,在vmm打算让一个guest os运行前,将要运行的guest os的二进制代码就被重写了,此时它会产生一个fault,然后vmm截取到以后,帮助guest os切换cr3,因为vmm知道guest os所谓的cr3的物理地址(其实在host上它就是一个文件映射进连续虚拟内存空间的一个虚拟地址)在哪里。
4.7.子进程运行。
     以上就是vmware虚拟化实现中最复杂的技术之一,内存的虚拟化,特别针对现代的32位保护模式硬件上的操作系统,它真的很复杂,其中涉及了BT技术,影子页表技术,ring1技术,其中在运行于ring0的vmm中实现mmu,然后提交给ring1的操作系统使用,这体现了设计者对内存访问流程是多么的理解。技术细节上需要说明的是,guest os的“内核页表”保持不变,它实现了第一层的映射,而vmm中的影子页表直接实现了第一层和第二层映射的组合映射,因此它必然需要时刻和真实的guest os页表进行同步操作,另外还有,由于这些guest os的物理内存实际上是vmm管理的.vmem文件映射的内存,因此这些“物理内存”是可以回写到磁盘.vmem文件的。
     理解了内存的虚拟化,io虚拟化就简单了,它被vmm捕获之后,就是模拟执行,在vmnet中,vmware-vmx在用户态模拟了虚拟机里面的网卡,使用的就是这个原理。甚至系统调用的过程也简单了,不过这涉及到x86的架构,和这里讨论的无关。
     虚拟一套x86机器的硬件系统,包括所有寄存器,中断等,然而中断几乎都是由host os来处理的,原因是这样的,因为guest os运行在ring1,而你的vmm运行在ring0,因此只要有硬件中断,cpu在执行guest os的下一条指令之前一看有if标志,因此它陷入ring0,也就是vmm,此时vmm切换回host os,由于重新载入了所有的idt等寄存器,所有host os完全可以处理这个中断,比如鼠标中断,vmware在用户态的vmware-vmx进程取到这个鼠标中断之后,发现当前的鼠标在虚拟机中,那么就会把这个事件发给vmm,然后vmm模拟一个中断交给guest os,切换到guest os由它的中断处理程序来处理之。
     也就是说,必然需要一个ring0的东西在运行,否则很多指令都没有办法执行的,将guest os放到ring1,这也就必然导致中断,io指令等都要由vmm来接管,vmm对于io来说,交给用户态的vmx,而对于中断则直接切回host os由之处理,对于guest os的用户态的int之类的指令,依然陷入vmm,然后vmm再转给ring1的guest os内核。

转载于:https://blog.51cto.com/dog250/1271125

vmware的原理和影子页表相关推荐

  1. KVM之EPT与影子页表(七)

    一.简述Linux内存映射 这部分其实是一个很庞大的话题,它包括分段.分页机制等,在不同架构.不同地址转换机制下,地址转换过程是不同的.本文的重点不在于这些复杂的分段分页保护机制.保护模式.实模式等内 ...

  2. Linux虚拟化:KVM影子页表

    影子页表简单来说就是,可以直接把客户端的虚拟地址映射成宿主端的物理地址. 2019年是崭新的一年,Linux kernel 5.0 低调发布了,给我的感觉就是,牛人不断在飞跃,我们也要策马奔腾赶紧追赶 ...

  3. 搬砖的成长之路——VMWare网络原理

    今天突然对多台服务器内部是如何联通进行通讯的感兴趣,所以学习了下.了解到VMWare网络中主要有三种模式: 目录 一.NAT模式(network address translation) 1.简介 2 ...

  4. VMWare快照原理(写时复制)?快照保护、快照克隆的作用?

    文章目录 快照原理 快照自动保护 快照与克隆区别 快照原理 数据保护方法有很多种,例如镜像.远程复制.多份拷贝.快照保护等等. 快照是磁盘的一种备份方式,是某一个时间点上某一个磁盘的数据备份,用户可以 ...

  5. VMware NSX原理与实践----NSX-MH解决方案

    各位客官给您请早了,早点已经给各位备好了,各位随时可以用餐 前序:前面的内容中给大家简单介绍了Xen和KVM,今天咱们进入正题,学习一下NSX-MH,看看它到底有什么不同 一.架构分析 NSX -MH ...

  6. VMware NSX原理与实践——NSX-V安装

    前序:前面的篇幅中已经讲述了NSX的基本架构,下面我将为各位小伙伴简单粗暴地讲解NSX的安装流程以及安装注意事项,如果各位小伙伴觉得哪里写的有问题,请及时和我沟通,我们一起进步. 一.安装的基本条件 ...

  7. VMware NSX原理与实践----NSX防火墙详解(一)

    **各位赶路的朋友们,天色已晚,前面方圆五十里没有其他的客栈了,夜间出行实在不妥,此地多有土匪横行,还是请各位店内歇息,明日再行赶路,乐意来客栈欢迎您!!!** 前序:前面的内容中介绍了防火墙的两种类 ...

  8. VMware NSX 原理与实践----逻辑路由以及二层网络

    前序:前面的文章中已经从NSX的基本架构讲到了逻辑交换,讲了什么是逻辑交换机,什莫是组播,什么是单播,讲了很多很多.希望大家能时常去复习,今天给大家讲一讲逻辑路由,也就是我们平时所说的三层通信. 一. ...

  9. VMware、KVM、Docker之虚拟化技术框架和原理——【转载自微信公众号开源linux】

    说起虚拟化你会想到什么?从我们常用的虚拟机三件套VMware.VirtualPC.VirutalBox到如今大火的KVM和容器技术Docker? 这些技术是什么关系,背后的技术原理是怎样的,又有什么样 ...

最新文章

  1. 提高网站页面收录的几个方法 返回列表 发新帖回复
  2. 华夏基金专访神策数据创始人兼 CEO 桑文锋,金融科技数字化趋势认知传递
  3. 在那天的雪停息之前β
  4. 基于redis 内存数据库简单使用
  5. 经纬度之间的距离计算
  6. 关于Debug.exe
  7. 《那些年啊,那些事——一个程序员的奋斗史》——37
  8. C语言中进制转换与函数
  9. pyechart基本图表
  10. STM32串口驱动安装攻略
  11. android11.0 Launcher3 高端定制之时钟动态图标
  12. OC5021B降压型恒流驱动控制芯片,关断时间可调
  13. TTL门电路与CMOS门电路
  14. Instrument初识
  15. 【POJ】1003_Hangover宿醉
  16. 自适应Simpson法P4525 【模板】自适应辛普森法1
  17. 你认为,做期货是基本面更有效还是技术面更有效?
  18. 连缀介绍和简单库对象
  19. slack软件怎么用
  20. 怎样更改软件默认安装路径由C盘到其他盘

热门文章

  1. centos 6 apt.sw.be 错误 无法yum安装软件解决方案
  2. bzoj3390[Usaco2004 Dec]Bad Cowtractors牛的报复*
  3. iPhone7,苹果最后的摇钱树
  4. 使用cronolog自动分割apache的日志。
  5. 国际化的支持--多编码问题
  6. 静态内容负载均衡的具体实现-续《几百元搞定大型网站》
  7. windows 开始命令集
  8. Pyotorch自定义损失函数
  9. HBase到MR再到HBase
  10. 使用大数据技术需要注意哪些问题