计算虚拟化之内存管理

news/2024/11/30 15:27:45/

CPU 的虚拟化是用户态的 qemu 和内核态的 KVM 共同配合完成的。它们二者通过 ioctl 进行通信。对于内存管理来讲,也是需要这两者配合完成的。

操作系统给每个进程分配的内存都是虚拟内存,需要通过页表映射,变成物理内存进行访问。当有了虚拟机之后,情况会变得更加复杂。因为虚拟机对于物理机来讲是一个进程,但是虚拟机里面也有内核,也有虚拟机里面跑的进程。所以有了虚拟机,内存就变成了四类:

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

内存映射对于虚拟机来讲是一件非常麻烦的事情,从 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 页表,也大大减少了内存的开销。

虚拟机的内存管理也是需要用户态的 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 页表,是否已经映射过,如果已经映射过,则经过四级页表映射,就能访问到物理页面。

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


http://www.ppmy.cn/news/39089.html

相关文章

netty 实现websocket 携带参数建立连接

Netty提供了很好的WebSocket支持,可以通过添加WebSocketServerProtocolHandler实现暴露一个WebSocket接口。但是,如果需要在WebSocket的URI中添加参数queryString,例如/im/ws?w221100234&t99,则连接可能无法建立,…

MySQL学习笔记(十五)——索引的创建和设计原则

1. 为什么使用索引 1.1 不加索引 没有索引,整张表读取数据,然后利用数据来比较条件,捞出符合条件的数据,表有很多数据,这些数据都会通过磁盘IO来读取,很耗时。 1.2 加索引 加索引后 ,通过索引…

Mybatis高阶使用

1.Mybatis拦截器 Mybatis——拦截器Interceptor_mybatis interceptor_七海健人的博客-CSDN博客 mybatis拦截器使用及原理_metaobject.forobject_huang_ma的博客-CSDN博客 手把手教你开发 MyBatis 插件 - 知乎 2.Mybatis工具类 MetaObject MetaClass https://www.cnblogs.co…

leetcode 面试题 17.06. 2出现的次数

编写一个方法,计算从 0 到 n (含 n) 中数字 2 出现的次数。 示例: 输入: 25 输出: 9 解释: (2, 12, 20, 21, 22, 23, 24, 25)(注意 22 应该算作两次) 该问题用的方法数数组dp,首先我通过总结规律写出了相关的code。使用一个dp数组记录10i10^i10i以内会出…

加多宝二次创业五周年:解锁品牌持续增长密码

今年作为后疫情时代元年,首要的任务是提振经济、重振信心,其中消费市场的提振至关重要。 春江水暖鸭先知。每当消费市场开始复苏,食品饮料行业的回暖一般会更明显。而要扩大食品饮料的消费规模、提振消费信心,关键在于品牌结合外…

NVIDIA jetson tensorrt加速yolov5摄像头检测

link 在使用摄像头直接检测目标时,检测的实时画面还是有点慢,下面是tensorrt加速过程记录。 一、设备 1、设备jetson agx xavier 2、jetpack4.6.1 3、tensorrt 8.2.1.8 4、conda虚拟环境 python3.6 二、虚拟环境搭建及依赖 1、参考此博客安装torch Nvidi…

13回归网络:HTTP/2是怎样的网络协议?

本篇文章我们先放下实践,回归网络,深入gRPC底层的HTTP/2协议,去探究一下框架底层网络协议的原理,提升对高性能网络协议的认知,相信读完这篇文章以后,我们就可以了解HTTP/2有哪些优势,为什么gRPC要使用HTTP/2作为底层的传输协议。 在众多研究HTTP/2的博客和资料中,最具…

银行数字化转型导师坚鹏:数字化转型背景下的银行对公客户营销

数字化转型背景下的银行对公客户营销课程背景: 数字化转型背景下,很多银行存在以下问题:不清楚如何搭建金融场景?不知道如何挖掘客户需求?不知道如何开展数字化营销? 课程特色:有实战案…