文章目录
qemu
是一个开源的机器与设备模拟器,其可以进行系统态模拟与用户态模拟。
- 其中系统态模拟主要指机器模拟,能支持的架构有很多,包括x86,power,arm,mips
- 用户态模拟指的是单个设备的仿真
QEMU可以与其他硬件虚拟加速模块配合使用,比如KQEMU, KVM,XEN等,也可以完全单独使用
KVM Kernel-based Virtual Machine
KVM(Kernel-based Virtual Machine)是一种基于Linux内核的开源虚拟化技术。是目前市面上最主流的虚拟化技术是kvm,各大云厂商的虚拟机大多是基于kvm的。
KVM 的本质就是一个 Linux Kernel Module,命名为 kvm.ko。需要硬件支持Intel VT或AMD-V技术。它将Linux内核转化为Hypervisor,通过内核模块kvm.ko 只管理虚拟CPU和内存,结合QEMU实现IO设备虚拟化。
KVM 运行在 Kernel space 且本身不具备任何设备模拟的能力。所以,KVM 还必须借助于一个运行在 User space 用户态的 Application(e.g. QEMU)来模拟 “组装“ 出一台完整 VM 所需要的各种虚拟设备(e.g. 网卡、显卡、存储控制器和硬盘)。
KMV性能高的原因:
- 直接利用硬件资源:KVM虚拟化技术直接利用宿主机的硬件资源,不需要额外的模拟和解释,因此性能非常高。根据测试,KVM虚拟机的性能可以达到宿主机的90%以上
- 高效的内存管理:KVM采用Linux内存管理机制,如KSM(内核同页合并),优化内存使用,降低内存压力
- 接近原生Linux性能:KVM利用Linux内核的虚拟化功能,确保了几乎没有性能开销,适合资源密集型应用
- 支持硬件虚拟化技术:KVM支持如Intel VT和AMD-V等CPU虚拟化扩展,这使得KVM能够直接访问硬件资源,提供接近物理服务器的性能
qemu+kvm
如下图所示,kvm.ko 运行在 Kernel space,并通过 /dev/kvm 文件向 User space 暴露了交互接口,同时也提供了 libkvm 函数库给 QEMU 进行 include。
EMU 通过 open() / close() 来打开/ 关闭 /dev/kvm 设备接口文件,并通过设备 I/O 接口 ioctl() 来调用 kvm.ko 提供的接口函数,以此来应用 KVM 基于硬件辅助虚拟化技术实现的 CPU 虚拟化、Memory 虚拟化、I/O 虚拟化等功能。此外的,VM 配置管理、VM 生命周期管理、VM 虚拟外设管理、以及一些特定的虚拟机技术(e.g. 动态迁移)等,则都由 QEMU 自己来实现。
KVM专注于核心虚拟化任务,例如CPU和内存的管理,而QEMU则负责硬件模拟
kvm负责cpu虚拟化+内存虚拟化,实现了cpu和内存的虚拟化,但kvm不能模拟其他设备;qemu可以模拟IO设备(网卡,磁盘),kvm加上qemu之后就能实现真正意义上服务器虚拟化。因为用到了上面两个东西,所以一般都称之为qemu-kvm。
qemu使用
sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build
sudo apt-get install git-email
sudo apt-get install libaio-dev libbluetooth-dev libcapstone-dev libbrlapi-dev libbz2-dev
sudo apt-get install libcap-ng-dev libcurl4-gnutls-dev libgtk-3-dev
sudo apt-get install libibverbs-dev libjpeg8-dev libncurses5-dev libnuma-dev
sudo apt-get install librbd-dev librdmacm-dev
sudo apt-get install libsasl2-dev libsdl2-dev libseccomp-dev libsnappy-dev libssh-dev
sudo apt-get install libvde-dev libvdeplug-dev libvte-2.91-dev libxen-dev liblzo2-dev
sudo apt-get install valgrind xfslibs-dev
sudo apt-get install libnfs-dev libiscsi-dev
下载qemu
https://github.com/qemu/qemu/tags
编译
cd qemu-9.2.3
mkdir build
cd build/
pip install tomli
apt install flex
apt install bison
…/configure
make (很慢)
创建磁盘镜像(qcow2为推荐格式)
./qemu-img create -f qcow2 mydisk.qcow2 10G
第一次启动,安装ios到我的硬盘
./qemu-system-x86_64 -m 2G -hda mydisk.qcow2 -cdrom /home/qemu/ubuntu-20.04.6-live-server-amd64.iso -boot order=d -nographic -serial mon:stdio
qemu启动需要三个东西
- qemu binary (qemu启动程序qemu-system-x86)
- ios 操作系统(安装时使用)
- 虚拟硬盘qcow2 文件系统镜像(文件都会放到这里,操作系统镜像也可以放到这里,就不需要ios文件了)
启动命令
./run_qemu_change.sh -q /usr/bin/qemu-system-x86_64 -k vmlinuz-5.15.0-58-generic -r initrd.img-5.15.0-58-generic -f vol.qcow2 -t qcow2 -R /dev/mapper/ubuntu--vg-ubuntu--lv -n 0 -s 5555
查看根文件目录映射路径 mount on / 就是 -R
启动参数配置
./qemu-system-x86_64 -kernel /path/to/kernel.img -initrd /path/to/initrd.img -hda /path/to/rootfs.img
-kernel 参数:指定内核镜像文件的路径(内核版本),这个操作系统中一版会自带
-initrd 参数:指定初始内存盘(initrd)路径,用于早期引导阶段。
-hda 参数:指定根文件系统镜像路径,可以是qcow2或者img格式
ps afjx | cat
提取kernel和init文件
在/boot/ 下
-device参数
在 QEMU 中,-device 参数用于向虚拟机添加设备。它允许你指定设备类型以及设备的参数,从而实现对虚拟硬件的细粒度控制。以下是关于 -device 参数的详细说明
device_name:设备类型,例如 virtio-net(网络设备)、virtio-blk(块设备)等。
参数:设备的可选参数,用于配置设备的行为。
常见设备类型
网络设备
virtio-net:Virtio 网络设备,适用于高性能网络模拟。
e1000:Intel E1000 网卡模拟,兼容性好,一版用这个
rtl8139:Realtek 8139 网卡模拟。
块设备
virtio-blk:Virtio 块设备,适用于高性能磁盘 I/O。
ide-hd:IDE 硬盘设备。
scsi-hd:SCSI 硬盘设备。
输入设备
usb-kbd:USB 键盘。
usb-mouse:USB 鼠标。
其他设备
virtio-rng:Virtio 随机数生成器。
virtio-serial:Virtio 串行设备。
virtio-gpu:Virtio 图形设备。
参数说明
id:设备的唯一标识符,用于后续引用。
bus:设备连接的总线。
addr:设备在总线上的地址。
drive:与设备关联的驱动器 ID(用于块设备)。
netdev:与设备关联的网络设备 ID(用于网络设备)。
mac:网络设备的 MAC 地址。
romfile:设备的 ROM 文件路径。
添加设备
qemu-system-x86_64 \
-machine q35 \
-device pcie-root-port,id=rp1 \
-device vfio-pci,host=01:00.0,bus=rp1
-device pcie-root-port,id=rp1,chassis=1,slot=1
这表示:
创建一个 PCIe 根端口
位于 1 号机箱chassis,单机系统通常为1,可不填
占用 1 号插槽位置slot,slot需要设备唯一,不同设备slot不同
比如
- 添加一个网卡
- 添加一个显卡
# 添加网卡设备
-nevdev=
-device pcie-root-port,id=rp1,slot=1 \
-device e1000,netdev=net0,bus=rp1 \
# 添加显卡设备
-device pcie-root-port,id=rp2,bus=pcie.0,slot=2 \
-device vfio-pci,host=8e:00.0,id=hostdev0,bus=rp2,addr=0x0
-device vfio-pci,host=0000:8e:00.0,id=hostdev0,bus=pci.4,addr=0x0
PCIe设备直通(PCI Passthrough)
需要条件:
- 主机支持IOMMU(VT-d/AMD-Vi)
- 内核参数启用IOMMU
- 设备未绑定主机驱动
- check是否支持
dmesg | grep -e DMAR -e IOMMU
如果输出中包含“IOMMU”或“DMAR”等信息,则说明IOMMU已启用 - check 内核参数启用IOMMU
cat /proc/cmdline
如果输出中包含intel_iommu=on或amd_iommu=on,则说明IOMMU在内核中已启用
如果没有则需要手动开通
vim /etc/default/grub
添加 intel_iommu=on iommu=pt
update-grub
然后重启 - 设备绑定主机驱动
绑定vfio(这一步和diag mx的 bind操作一样)
lspci -tvnn
echo vfio-pci | tee /sys/bus/pci/devices/0000:8e:00.0/driver_override
echo 0000:8e:00.0 | tee /sys/bus/pci/drivers/vfio-pci/bind
lspci -vvv -s 8e:00.0
虚拟机网络配置
在QEMU中,使用-netdev参数可以创建和配置虚拟机的网络设备。-netdev参数用于定义网络后端(如TAP设备、用户模式网络等),而-device参数用于将虚拟网卡连接到这个网络后端。
在QEMU的用户模式网络(User Mode Network)中,默认情况下虚拟机无法直接与宿主机通信,因为虚拟机的网络是通过QEMU的内置NAT实现的。虚拟机可以访问外部网络(如互联网),但无法直接访问宿主机的本地服务或与宿主机通信。
不过,可以通过以下方法实现虚拟机与宿主机的通信:
以下是几种常见的-netdev用法示例:
- 用户模式网络(User Mode Network)
用户模式网络是最简单的网络配置方式,它允许虚拟机通过QEMU的内置NAT访问宿主机的网络,但虚拟机无法直接与宿主机通信。虚拟机可以ping通外面,但是host ping不通里面
qemu-system-x86_64 -hda /path/to/disk.img -netdev user,id=net0 -device e1000,netdev=net0
- TAP设备(TAP Network)
TAP设备允许虚拟机通过桥接网络与宿主机直接通信。需要手动创建TAP设备并将其桥接到宿主机的物理网卡。
qemu-system-x86_64 -hda /path/to/disk.img -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device e1000,netdev=net0
- 桥接网络(Bridge Network)
桥接网络允许虚拟机直接连接到宿主机的物理网络,与宿主机在同一网络中。
qemu-system-x86_64 -hda /path/to/disk.img -netdev bridge,br=br0,id=net0 -device e1000,netdev=net0
- 宿主机网络(Host Network)
宿主机网络模式允许虚拟机直接访问宿主机的网络栈,但虚拟机无法直接与外部网络通信。
qemu-system-x86_64 -hda /path/to/disk.img -netdev socket,id=net0,listen=127.0.0.1:1234 -device e1000,netdev=net0
- VLAN网络(VLAN Network)
VLAN网络允许虚拟机连接到特定的VLAN。
qemu-system-x86_64 -hda /path/to/disk.img -netdev tap,id=net0,ifname=tap0,vlan=10 -device e1000,netdev=net0
桥接网络配置
sudo apt-get install bridge-utils
- 修改netplan 文件
这里注意空格一定是2个缩进,不要用tab
ethernets 为ip a显示的以太网名称 - netplan apply
- 成功后看到添加的桥
或者
- 启动虚拟机