QEMU 学习记录

什么是 KVM?

基于内核的虚拟机 Kernel-based Virtual Machine(KVM)是一种内建于 Linux 中的开源虚拟化技术。具体而言,KVM 可帮助用户将 Linux 转变为虚拟机监控程序,使主机计算机能够运行多个隔离的虚拟环境,即虚拟客户机或虚拟机(VM)。

什么是 QEMU?

Qemu 是一个完整的可以单独运行的软件,它可以用来模拟不同架构的机器,非常灵活和可移植。它主要通过一个特殊的’重编译器’将为特定处理器编写二进制代码转换为另一种。

KVM 与 QEMU 的关系

KVM 是 Linux 的一个模块。可以用modprobe去加载 KVM 模块。加载了模块后,才能进一步通过其他工具创建虚拟机。但仅有 KVM 模块是 远远不够的,因为用户无法直接控制内核模块去作事情:还必须有一个用户空间的工具才行。这个用户空间的工具,开发者选择了已经成型的开源虚拟化软件 QEMU。KVM 使用了 QEMU 的一部分,并稍加改造,就成了可控制 KVM 的用户空间工具了。所以你会看到,官方提供的 KVM 下载有两 大部分三个文件,分别是 KVM 模块、QEMU 工具以及二者的合集。也就是说,你可以只升级 KVM 模块,也可以只升级 QEMU 工具。

QEMU 用户模式与系统模式

QEMU 属于应用层的仿真程序,它支持两种操作模式:用户模式模拟和系统模式模拟。

  • 用户模式仿真 利用动态代码翻译机制,可以在当前 CPU 上执行被编译为支持其他 CPU 的程序,如可以在 x86 机器上执行一个 ARM 二进制可执行程序。(执行主机 CPU 指令的动态翻译并相应地转换 Linux 系统调用)。
  • 系统模式仿真 利用其它 VMM(Xen, KVM) 来使用硬件提供的虚拟化支持,创建接近于主机性能的全功能虚拟机,包括处理器和配套的外围设备(磁盘,以太网等)。

用户模式

支持的 CPU:x86 (32 and 64 bit), PowerPC (32 and 64 bit), ARM, MIPS (32 bit only), Sparc (32 and 64 bit), Alpha, ColdFire(m68k), CRISv32 和 MicroBlaze 下列操作系统支持 QEMU 的用户模式模拟:

  • Linux (referred as qemu-linux-user)
  • BSD (referred as qemu-bsd-user)

调用(具体参数含义

qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] [-B offset] [-R size] program [arguments...]

用户模式模拟环境下运行速度要比系统模式模拟环境下快,但并不是完美模拟,比如程序读取/proc/cpuinfo内容时,由主机内核返回,因此返回的信息是描述主机 CPU 的,而不是模拟的 CPU。

系统模式

首先创建虚拟镜像,模拟硬盘空间:

root@hanhan:/home/dominic/qemu/# qemu-img create -f qcow2 qmtest.img 10G
Formatting 'qmtest.img', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off 
root@hanhan:/home/dominic/qemu/# ls
qmtest.img

-f选项用于指定镜像的格式,qcow2格式是 QEMU 最常用的镜像格式,采用写时复制技术来优化性能。qmtest.img是镜像文件的名字,10G是镜像文件大小。

镜像文件创建完成后,可使用qemu-system-x86来启动x86架构的虚拟机:

qemu-system-x86_64 qmtest.img

qmtest.img 中还未安装操作系统,所以会提示“No bootable device”的错误。

其次,准备操作系统镜像 下载需要的 Linux 发行版镜像文件,https://launchpad.net/ubuntu/+cdmirrors,找到想要下载的镜像,这里以交通大学的镜像为例 右击链接复制地址:https://ftp.sjtu.edu.cn/ubuntu-cd/20.10/ubuntu-20.10-live-server-amd64.iso

root@hanhan:/home/dominic/qemu/# wget https://ftp.sjtu.edu.cn/ubuntu-cd/20.10/ubuntu-20.10-live-server-amd64.iso

最后,启动虚拟机安装操作系统

root@hanhan:/home/dominic/qemu/# qemu-system-x86_64 -m 2048 -enable-kvm qmtest.img -cdrom ./Fedora-Live-Desktop-x86_64-20-1.iso

-m指定虚拟机内存大小,默认单位是 MB,-enable-kvm使用 KVM 进行加速,-cdrom添加 fedora 的安装镜像。

该模式下,要比用户模式模拟慢得多,因为模拟了目标内核,以及设备输入/输出、中断等。

QEMU 工作原理

Responsive Image

单纯使用 qemu,采用的是完全虚拟化的模式。qemu 向 Guest OS 模拟 CPU,也模拟其他的硬件,GuestOS 认为自己和硬件直接打交道,其实是同 qemu 模拟出来的硬件打交道,qemu 会将这些指令转译给真正的硬件。由于所有的指令都要从 qemu 里面过一手,因而性能就会比较差。

完全虚拟化是非常慢的,所以要使用硬件辅助虚拟化技术 Intel-VTAMD-V,所以需要 CPU 硬件开启这个标志位,一般在 BIOS 里面设置。当确认开始了标志位之后,通过KVM,GuestOS 的 CPU 指令不用经过 Qemu 转译,直接运行,大大提高了速度。所以,KVM 在内核里面需要有一个模块,来设置当前 CPU 是 Guest OS 在用,还是 Host OS 在用。

可以通过如下命令查看内核模块中是否有 KVM

lsmod | grep kvm

KVM 内核模块通过 /dev/kvm 暴露接口,用户态程序可以通过 ioctl来访问这个接口。Qemu 将 KVM 整合进来,将有关 CPU 指令的部分交由内核模块来做,就是 qemu-kvm (qemu-system-XXX)

qemu 和 kvm 整合之后,CPU 的性能问题解决了。另外 Qemu 还会模拟其他的硬件,如网络和硬盘。同样,全虚拟化的方式也会影响这些设备的性能。

于是,qemu 采取半虚拟化的方式,让 Guest OS 加载特殊的驱动来做这件事情。

例如,网络需要加载 virtio_net,存储需要加载 virtio_blk,Guest 需要安装这些半虚拟化驱动,GuestOS 知道自己是虚拟机,所以数据会直接发送给半虚拟化设备,经过特殊处理(例如排队、缓存、批量处理等性能优化方式),最终发送给真正的硬件。这在一定程度上提高了性能。

Q : 系统模式和用户模式的区别? 系统模式 是 qemu 虚拟出一套完整的硬件环境,包含 CPU,内存,网卡,硬盘,对于虚拟机上运行的 OS 看到的和硬件和真实的是一样的。 用户模式是直接将可执行的文件进行指令翻译,只虚拟出 CPU。 假设有 KVM:host 是 x86,QEMU 虚拟出 x86 的系统模式 运行 Windows 系统。QEMU 会将 Windows 指令直接交给 host CPU 直接运行(这个功能是由 KVM 实现的,相当于直接调用 host CPU),性能损失小。内存,硬盘,网络等外设是由 qemu 虚拟出来的。 假设无 KVM:host 是 x86,QEMU 虚拟出 x86 的系统模式运行 Windows 系统。QEMU 会将 Windows 指令翻译成中间码,中间码再转成 host CPU 指令(这个功能是由 qemu TCG 实现的),性能损失大。内存,硬盘,网洛等外设是由 qemu 虚拟出来的。 假设有 KVM:host 是 x86,QEMU 虚拟出 RISC-V 的系统模式 运行 Linux 系统。QEMU 会将 Linux 指令翻译成中间码,中间码再转成 host CPU 指令(这个功能是由 qemu TCG 实现的),性能损失大。内存,硬盘,网洛等外设是由 qemu 虚拟出来的。 KVM 需要在虚拟机与宿主机架构相同时才生效。 此外,用户模式下调用 IO 硬件会报错。qemu 系统模式下会模拟出所有设备,但是模拟的 IO 设备效率低,所以后来有了半虚拟化。