计算虚拟化之内存

有了虚拟机,内存就变成了四类:

  • 虚拟机里面的虚拟内存(Guest OS Virtual Memory,GVA),这是虚拟机里面的进程看到的内存空间;
  • 虚拟机里面的物理内存(Guest OS Physical Memory,GPA),这是虚拟机里面的操作系统看到的内存,它认为这是物理内存;
  • 物理机的虚拟内存(Host Virtual Memory,HVA),这是物理机上的 qemu 进程看到的内存空间;
  • 物理机的物理内存(Host Physical Memory,HPA),这是物理机上的操作系统看到的内存。

由于 CPU 和内存是紧密结合的,因而内存虚拟化的初始化过程,和 CPU 虚拟化的初始化是一起完成的。

内存映射对于虚拟机来讲是一件非常麻烦的事情,从 GVA 到 GPA 到 HVA 到 HPA,性能很差,为了解决这个问题,有两种主要的思路。

第一种方式就是软件的方式,影子页表  (Shadow Page Table)。

内存映射要通过页表来管理,页表地址应该放在 cr3 寄存器里面。本来的过程是,客户机要通过 cr3 找到客户机的页表,实现从 GVA 到 GPA 的转换,然后在宿主机上,要通过 cr3 找到宿主机的页表,实现从 HVA 到 HPA 的转换。

为了实现客户机虚拟地址空间到宿主机物理地址空间的直接映射。客户机中每个进程都有自己的虚拟地址空间,所以 KVM 需要为客户机中的每个进程页表都要维护一套相应的影子页表。

在客户机访问内存时,使用的不是客户机的原来的页表,而是这个页表对应的影子页表,从而实现了从客户机虚拟地址到宿主机物理地址的直接转换。而且,在 TLB 和 CPU 缓存上缓存的是来自影子页表中客户机虚拟地址和宿主机物理地址之间的映射,也因此提高了缓存的效率。

但是影子页表的引入也意味着 KVM 需要为每个客户机的每个进程的页表都要维护一套相应的影子页表,内存占用比较大,而且客户机页表和和影子页表也需要进行实时同步。

第二种方式,就是硬件的方式,Intel 的 EPT(Extent Page Table,扩展页表)技术。

EPT 在原有客户机页表对客户机虚拟地址到客户机物理地址映射的基础上,又引入了 EPT 页表来实现客户机物理地址到宿主机物理地址的另一次映射。客户机运行时,客户机页表被载入 CR3,而 EPT 页表被载入专门的 EPT 页表指针寄存器 EPTP。

有了 EPT,在客户机物理地址到宿主机物理地址转换的过程中,缺页会产生 EPT 缺页异常。KVM 首先根据引起异常的客户机物理地址,映射到对应的宿主机虚拟地址,然后为此虚拟地址分配新的物理页,最后 KVM 再更新 EPT 页表,建立起引起异常的客户机物理地址到宿主机物理地址之间的映射。

KVM 只需为每个客户机维护一套 EPT 页表,也大大减少了内存的开销。

因为使用了 EPT 之后,客户机里面的页表映射,也即从 GVA 到 GPA 的转换,还是用传统的方式,和在内存管理那一章讲的没有什么区别。而 EPT 重点帮我们解决的就是从 GPA 到 HPA 的转换问题。因为要经过两次页表,所以 EPT 又称为 tdp(two dimentional paging)。

EPT 的页表结构也是分为四层,EPT Pointer (EPTP)指向 PML4 的首地址。

管理物理页面的 Page 结构和咱们讲内存管理那一章是一样的。EPT 页表也需要存放在一个页中,这些页要用 kvm_mmu_page 这个结构来管理。

虚拟机的内存管理也是需要用户态的 qemu 和内核态的 KVM 共同完成。为了加速内存映射,需要借助硬件的 EPT 技术。

在用户态 qemu 中,有一个结构 AddressSpace address_space_memory 来表示虚拟机的系统内存,这个内存可能包含多个内存区域 struct MemoryRegion,组成树形结构,指向由 mmap 分配的虚拟内存。

在 AddressSpace 结构中,有一个 struct KVMMemoryListener,当有新的内存区域添加的时候,会被通知调用 kvm_region_add 来通知内核。

在用户态 qemu 中,对于虚拟机有一个结构 struct KVMState 表示这个虚拟机,这个结构会指向一个数组的 struct KVMSlot 表示这个虚拟机的多个内存条,KVMSlot 中有一个 void *ram 指针指向 mmap 分配的那块虚拟内存。

kvm_region_add 是通过 ioctl 来通知内核 KVM 的,会给内核 KVM 发送一个 KVM_SET_USER_MEMORY_REGION 消息,表示用户态 qemu 添加了一个内存区域,内核 KVM 也应该添加一个相应的内存区域。

和用户态 qemu 对应的内核 KVM,对于虚拟机有一个结构 struct kvm 表示这个虚拟机,这个结构会指向一个数组的 struct kvm_memory_slot 表示这个虚拟机的多个内存条,kvm_memory_slot 中有起始页号,页面数目,表示这个虚拟机的物理内存空间。

虚拟机的物理内存空间里面的页面当然不是一开始就映射到物理页面的,只有当虚拟机的内存被访问的时候,也即 mmap 分配的虚拟内存空间被访问的时候,先查看 EPT 页表,是否已经映射过,如果已经映射过,则经过四级页表映射,就能访问到物理页面。

如果没有映射过,则虚拟机会通过 VM-Exit 指令回到宿主机模式,通过 handle_ept_violation 补充页表映射。先是通过 handle_mm_fault 为虚拟机的物理内存空间分配真正的物理页面,然后通过 __direct_map 添加 EPT 页表映射。

此文章为11月Day30学习笔记,内容来源于极客时间《趣谈Linux操作系统》,推荐该课程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/235547.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新金融时代、AMCAP谱写财富梦想新篇章

近年来,智能配置投资与理财逐渐受到关注并走俏。这是一种简单快捷的智慧化理财方式,通过将个人和家族的闲置资金投入到低风险高流动性的产品中。 国际财富管理投资机构AMCAP集团金融分析师表示:智能配置投资与理财之所以持续走俏&#xff0c…

msvcp140.dll的解决方法有哪些。详细解析五种可以修复msvcp140.dll丢失的方法

引言: 在日常使用电脑的过程中,我们可能会遇到一些错误提示,其中之一就是“msvcp140.dll丢失”。那么,什么是msvcp140.dll文件?它的作用是什么?当它丢失时会对电脑产生什么影响?本文将详细介绍…

2021年8月18日 Go生态洞察:整合Go的网络体验

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

Vue实现图片预览(Viewer.js)

摘要: vue项目开发中遇到一个图片预览的需求,可以切换下一张,就是花里胡哨的,所以找viewer.js的插件 npm install v-viewer -S在项目main.js中加入: Viewer.setDefaults用于更改默认配置,比如我不想要显示…

windows下使用iperf3

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、使用步骤1.下载2.解压3.测试1.作为服务器使用2.作为客户端使用 总结 前言 windows使用iperf3和linux是一样的,而且可以相互操作。 一、使用步骤…

Linux常用命令——mv命令

文章目录 1. 简介2. 命令格式3. 主要参数4. 常见用法及示例4.1 移动文件4.2 重命名文件4.3 交互式移动文件4.4 强制移动文件4.5 移动多个文件4.6 使用通配符移动文件 5. 注意事项6. 结论 1. 简介 mv 命令在Linux系统中用于移动文件或目录,同时也可以用于重命名文件…

力扣 --- 删除有序数组中的重复项 II

题目描述: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的…

QT 项目中添加文件夹(分类文件)

为了更方便的整理项目的文件,添加文件夹把文件进行分类。 1.首先在项目文件中创建新的文件夹 2.把需要归类的文件放入新建的文件中 3.右键然后选择add..... 4.运行此程序,会报错因为文件路径改变了,需要在.pro中修改路径 注意事项 文件夹内部…

[c++]——string类____详细初步了解string类的运用

在成为大人的路上喘口气. 目录 🎓标准库类型string 🎓定义和初始化string对象 💻string类对象的常见构造 💻string类对象的不常见构造 💻读写string对象 🎓 string类对象的修改操作 &#x1f4…

opencv知识库:cv2.add()函数和“+”号运算符

需求场景 现有一灰度图像,需求是为该图像增加亮度。 原始灰度图像 预期目标图像 解决方案 不建议的方案——“”运算符 假设我们需要为原始灰度图像的亮度整体提升88,那么利用“”运算符的源码如下: import cv2img_path r"D:\pych…

v-model(双向数据绑定)自动收集数据

v-model 是 Vue 中一个常用的指令,用于实现表单元素与数据的双向绑定。 它的实现原理主要基于以下两个方面: 语法实现: v-model 实际上是 Vue 对 :value 和 input 两个属性的语法糖。当我们在组件中使用 v-model 指令时,Vue 会根…

C# Onnx 百度飞桨开源PP-YOLOE-Plus目标检测

目录 效果 模型信息 项目 代码 下载 C# Onnx 百度飞桨开源PP-YOLOE-Plus目标检测 效果 模型信息 Inputs ------------------------- name:image tensor:Float[1, 3, 640, 640] name:scale_factor tensor:Float[1, 2] ----…