文章目录

  • 虚拟机
  • CPU 的虚拟化过程
  • 存储虚拟化
  • 网络虚拟化场景下网络包的发送过程

虚拟机

  • 虚拟化的本质是用 qemu 的软件模拟硬件,但是模拟方式比较慢,需要加速;
  • 虚拟化主要模拟 CPU、内存、网络、存储,分别有不同的加速办法;
  • CPU 和内存主要使用硬件辅助虚拟化进行加速,需要配备特殊的硬件才能工作;
  • 网络和存储主要使用特殊的半虚拟化驱动加速,需要加载特殊的驱动程序。

CPU 的虚拟化过程

  • 首先,我们要定义 CPU 这种类型的 TypeInfo 和 TypeImpl、继承关系,并且声明它的类初始化函数。
  • 在 qemu 的 main 函数中调用 MachineClass 的 init 函数,这个函数既会初始化 CPU,也会初始化内存。
  • CPU 初始化的时候,会调用 pc_new_cpu 创建一个虚拟 CPU,它会调用 CPU 这个类的初始化函数。
  • 每一个虚拟 CPU 会调用 qemu_thread_create 创建一个线程,线程的执行函数为 qemu_kvm_cpu_thread_fn。
  • 在虚拟 CPU 对应的线程执行函数中,我们先是调用 kvm_vm_ioctl(KVM_CREATE_VCPU),在内核的 KVM 里面,创建一个结构 struct vcpu_vmx,表示这个虚拟 CPU。在这个结构里面,有一个 VMCS,用于保存当前虚拟机 CPU 的运行时的状态,用于状态切换。
  • 在虚拟 CPU 对应的线程执行函数中,我们接着调用 kvm_vcpu_ioctl(KVM_RUN),在内核的 KVM 里面运行这个虚拟机 CPU。运行的方式是保存宿主机的寄存器,加载客户机的寄存器,然后调用 __ex(ASM_VMX_VMLAUNCH) 或者 __ex(ASM_VMX_VMRESUME),进入客户机模式运行。一旦退出客户机模式,就会保存客户机寄存器,加载宿主机寄存器,进入宿主机模式运行,并且会记录退出虚拟机模式的原因。大部分的原因是等待 I/O,因而宿主机调用 kvm_handle_io 进行处理。

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

  • 第一种方式就是软件的方式,影子页表 (Shadow Page Table):内存映射要通过页表来管理,页表地址应该放在 cr3 寄存器里面。本来的过程是,客户机要通过 cr3 找到客户机的页表,实现从 GVA 到 GPA 的转换,然后在宿主机上,要通过 cr3 找到宿主机的页表,实现从 HVA 到 HPA 的转换。为了实现客户机虚拟地址空间到宿主机物理地址空间的直接映射。客户机中每个进程都有自己的虚拟地址空间,所以 KVM 需要为客户机中的每个进程页表都要维护一套相应的影子页表。在客户机访问内存时,使用的不是客户机的原来的页表,而是这个页表对应的影子页表,从而实现了从客户机虚拟地址到宿主机物理地址的直接转换。而且,在 TLB 和 CPU 缓存上缓存的是来自影子页表中客户机虚拟地址和宿主机物理地址之间的映射,也因此提高了缓存的效率。但是影子页表的引入也意味着 KVM 需要为每个客户机的每个进程的页表都要维护一套相应的影子页表,内存占用比较大,而且客户机页表和和影子页表也需要进行实时同步。
  • 第二种方式就是硬件的方式,EPT(Extent Page Table,扩展页表):PT 在原有客户机页表对客户机虚拟地址到客户机物理地址映射的基础上,又引入了 EPT 页表来实现客户机物理地址到宿主机物理地址的另一次映射。客户机运行时,客户机页表被载入 CR3,而 EPT 页表被载入专门的 EPT 页表指针寄存器 EPTP。有了 EPT,在客户机物理地址到宿主机物理地址转换的过程中,缺页会产生 EPT 缺页异常。KVM 首先根据引起异常的客户机物理地址,映射到对应的宿主机虚拟地址,然后为此虚拟地址分配新的物理页,最后 KVM 再更新 EPT 页表,建立起引起异常的客户机物理地址到宿主机物理地址之间的映射。KVM 只需为每个客户机维护一套 EPT 页表,也大大减少了内存的开销。

存储虚拟化

存储虚拟化的过程分为前端、后端和中间的队列。

  • 前端有前端的块设备驱动 Front-end driver,在客户机的内核里面,它符合普通设备驱动的格式,对外通过 VFS 暴露文件系统接口给客户机里面的应用。
  • 后端有后端的设备驱动 Back-end driver,在宿主机的 qemu 进程中,当收到客户机的写入请求的时候,调用文件系统的 write 函数,写入宿主机的 VFS 文件系统,最终写到物理硬盘设备上的 qcow2 文件。
  • 中间的队列用于前端和后端之间传输数据,在前端的设备驱动和后端的设备驱动,都有类似的数据结构 virt-queue 来管理这些队列.

存储虚拟化的场景下,整个写入的过程

  • 在虚拟机里面,应用层调用 write 系统调用写入文件。
  • write 系统调用进入虚拟机里面的内核,经过 VFS(虚拟文件系统),通用块设备层,I/O 调度层,到达块设备驱动。
  • 虚拟机里面的块设备驱动是 virtio_blk,它和通用的块设备驱动一样,有一个 request queue,另外有一个函数 make_request_fn 会被设置为 blk_mq_make_request,这个函数用于将请求放入队列。
  • 虚拟机里面的块设备驱动是 virtio_blk 会注册一个中断处理函数 vp_interrupt。当 qemu 写入完成之后,它会通知虚拟机里面的块设备驱动。
  • blk_mq_make_request 最终调用 virtqueue_add,将请求添加到传输队列 virtqueue 中,然后调用 virtqueue_notify 通知 qemu。
  • 在 qemu 中,本来虚拟机正处于 KVM_RUN 的状态,也即处于客户机状态。
  • qemu 收到通知后,通过 VM exit 指令退出客户机状态,进入宿主机状态,根据退出原因,得知有 I/O 需要处理。
  • qemu 调用 virtio_blk_handle_output,最终调用 virtio_blk_handle_vq。
  • virtio_blk_handle_vq 里面有一个循环,在循环中,virtio_blk_get_request 函数从传输队列中拿出请求,然后调用 virtio_blk_handle_request 处理请求。
  • virtio_blk_handle_request 会调用 blk_aio_pwritev,通过 BlockBackend 驱动写入 qcow2 文件。
  • 写入完毕之后,virtio_blk_req_complete 会调用 virtio_notify 通知虚拟机里面的驱动。数据写入完成,刚才注册的中断处理函数 vp_interrupt 会收到这个通知。

网络虚拟化场景下网络包的发送过程

  • 在虚拟机里面的用户态,应用程序通过 write 系统调用写入 socket。
  • 写入的内容经过 VFS 层,内核协议栈,到达虚拟机里面的内核的网络设备驱动,也即 virtio_net。
  • virtio_net 网络设备有一个操作结构 struct net_device_ops,里面定义了发送一个网络包调用的函数为 start_xmit。
  • 在 virtio_net 的前端驱动和 qemu 中的后端驱动之间,有两个队列 virtqueue,一个用于发送,一个用于接收。然后,我们需要在 start_xmit 中调用 virtqueue_add,将网络包放入发送队列,然后调用 virtqueue_notify 通知 qemu。
  • qemu 本来处于 KVM_RUN 的状态,收到通知后,通过 VM exit 指令退出客户机模式,进入宿主机模式。发送网络包的时候,virtio_net_handle_tx_bh 函数会被调用。
  • 接下来是一个 for 循环,我们需要在循环中调用 virtqueue_pop,从传输队列中获取要发送的数据,然后调用 qemu_sendv_packet_async 进行发送。
  • qemu 会调用 writev 向字符设备文件写入,进入宿主机的内核。
  • 在宿主机内核中字符设备文件的 file_operations 里面的 write_iter 会被调用,也即会调用 tun_chr_write_iter。
  • 在 tun_chr_write_iter 函数中,tun_get_user 将要发送的网络包从 qemu 拷贝到宿主机内核里面来,然后调用 netif_rx_ni 开始调用宿主机内核协议栈进行处理。
  • 宿主机内核协议栈处理完毕之后,会发送给 tap 虚拟网卡,完成从虚拟机里面到宿主机的整个发送过程。

    你知道的越多,你不知道的越多。
    有道无术,术尚可求,有术无道,止于术。
    如有其它问题,欢迎大家留言,我们一起讨论,一起学习,一起进步

Linux操作系统之虚拟化相关推荐

  1. [ kvm ] 学习笔记 1:Linux 操作系统及虚拟化

    1. 前言 一台计算机是由一堆硬件设备组合而成,在硬件之上是操作系统,操作系统与计算机硬件密不可分,操作系统用来管理所有的硬件资源提供服务,各个硬件设备是通过 总线 进行连接起来的: 在操作系统之上, ...

  2. KVM-1、Linux 操作系统及虚拟化

    1. 前言 一台计算机是由一堆硬件设备组合而成,在硬件之上是操作系统,操作系统与计算机硬件密不可分,操作系统用来管理所有的硬件资源提供服务,各个硬件设备是通过 总线 进行连接起来的: 在操作系统之上, ...

  3. Linux操作系统及平台虚拟化技术漫谈

    虚拟化Linux可以通过很多技术来实现,包括从平台到操作系统虚拟化.实际上,Linux可以说是唯一一个具有广泛虚拟化解决方案的操作系统.在本文中,我们将讨论实现Linux虚拟化的多种方式,以及Linu ...

  4. Oracle基于Linux平台的虚拟化与云计算战略

    凭借Linux环境的开放优势与开源的影响力,在开源架构上实现虚拟化是很多企业用户关心的问题.07年以来,虚拟化技术在中国市场中名声大噪,以红帽.Novell为代表的Linux供应商开始注重在市场中宣传 ...

  5. Linux 操作系统原理 — 进程与线程管理

    目录 文章目录 目录 前言 进程与线程 内核线程,用户线程与轻量级进程 内核线程 轻量级进程 用户线程 轻量级进程与用户线程的区别 用户线程与轻量级进程的混合模式 用户线程和内核线程的区别 线程的实现 ...

  6. 操作系统级虚拟化概述

    2019独角兽企业重金招聘Python工程师标准>>> 操作系统级虚拟化 KVM.XEN等虚拟化技术允许各个虚拟机拥有自己独立的操作系统.与KVM.XEN等虚拟化技术不同,所谓操作系 ...

  7. [转帖]爬过这 6 个坡,你就能对 Linux 操作系统了如指掌

    爬过这 6 个坡,你就能对 Linux 操作系统了如指掌 http://www.51testing.com/html/16/n-4461316.html 学习的任务 任重道远 我现在处于第一阶段. 发 ...

  8. 操作系统与虚拟化安全第一次作业-关键习题

    <操作系统与虚拟化安全> 第一次作业(预备知识)本次作业要求: 1.  这是个人作业,每位同学独立完成和提交. 2.  提交时间10月13日24点. 3.  如果遇到问题,请联系助教. 一 ...

  9. Linux 操作系统太难?先爬过这 6 个陡坡

    如今的软件开发行业,服务器端市场基本被 Linux 系统占领了.移动端中的 Android 系统是基于 Linux 内核开发的,那些很火的虚拟化.消息队列.云计算.大数据等技术,都默认支持 Linux ...

最新文章

  1. English Speech-Graduation from University
  2. redis sds的申请扩容源码
  3. kinect1+depthimage_to_laserscan
  4. 【java】阿里为什么推荐使用LongAdder,而不是volatile?
  5. windows安装ubuntu系统的注意事项小记
  6. 一文了解plc编程、电脑编程、手机APP编程、组态编程、云编程(下)
  7. java red5 流媒体服务_[Red5]Red5之Flash流媒体服务器的安装与使用教程完整版(组图)...
  8. 带你快速了解ISO27001信息安全管理体系认证
  9. 局计算机房制度,岳阳市统计局机房管理制度
  10. C#.NET 将日期转换为大写
  11. iPhone X 的适配
  12. mysql数据写入磁盘的原理_WAL(Write Ahead Log)机制解析
  13. android studio虚拟机图库不显示图片,照片显示图片解决办法
  14. unity替换模型材质
  15. 微服务启动成功无法注册到服务注册中心
  16. opencv的Mat中step的解释
  17. java的字节码文件是什么后缀_【Java虚拟机1】Java字节码文件格式入门
  18. Yocto系列讲解[理论篇]31 - Linux kernel相关的任务
  19. C++文件操作API函数介绍
  20. 深度思考:无关生智,局外生慧

热门文章

  1. /usr/bin/ld: /tmp/ccIHWHTn.o: in function `Cdisk::Cdisk()‘:编译报错解决方案
  2. java 获取集合对象中某个属性不为空的数据集合 lambda获取【拉姆达表达式 】
  3. java实现易宝支付
  4. 大数据开发之Hive篇14-Hive归档(Archiving)
  5. JSK-107305丨ICPC焦作站网赛 B丨dp
  6. XCode 报错Thread 2:signal SIGABRT
  7. java多边形填充_关于java:从图像(填充形状)生成多边形
  8. 计算机内存条如何区分频率,Win7怎么看内存条频率,教您查看方法
  9. VM下Centos7虚拟机无法进入图形界面并提示Started Virtualization daemon...ices..shutdown
  10. 奇数值结点链表 (20 分)