Qemu

来自百合仙子's Wiki
跳转到导航 跳转到搜索

磁盘镜像

创建:

qemu-img create -f qcow2 -o lazy_refcounts=on,compression_type=zstd ArchVM.img 15G
# 使用“母镜像”功能 
qemu-img create -f qcow2 -o lazy_refcounts=on,compression_type=zstd -b ArchVM.img ArchTest.img

转换压缩格式:

qemu-img convert -p -m8 -c -O qcow2 -o lazy_refcounts=on,compression_type=zstd ArchLinuxKDE.qcow2 ArchLinuxKDE-new2.qcow2

zstd 比默认的 zlib 压缩率高不少:

格式/压缩 大小
raw 6.64 GiB
qcow2/zlib 6.75 GiB
qcow2/zstd 4.17 GiB

启动命令

Arch Linux 服务器

#!/bin/sh
exec qemu-system-x86_64 -enable-kvm \
       -cpu host \
       -drive file=$HOME/ArchTest.img,if=virtio \
       -netdev user,id=vmnic,hostname=archvm,hostfwd=tcp:127.0.0.1:2222-:22 \
       -device virtio-net,netdev=vmnic \
       -m 512M \
       -curses \
       -name "Arch VM" \
       "$@"

如果要从 ISO 镜像启动,加参数:

-boot d -cdrom path_to_file.iso

如果没有图形界面,可使用 -curses 来显示文本终端。因此需要加上内核参数 nomodesetgrub 需要去掉关于gfx 的部分。isolinux 可按Tab然后添加内核参数。

要使用 VNC,使用如下参数:

-vga std -nographic -vnc :0

Arch Linux 桌面

一个运行图形环境的例子(需要将 allow br0 写入 /etc/qemu/bridge.conf 以使用桥接网络接口):

#!/bin/sh
exec qemu-system-x86_64 -enable-kvm \
       -name "ArchKDE" \
       -cpu host -smp 4 \
       -m 4G -machine q35 \
       -device intel-iommu \
       -drive file=/.../ArchLinuxKDE.qcow2,if=virtio \
       -netdev bridge,id=eth0,br=br0 \
       -device virtio-net,netdev=eth0 \
       -vga virtio \
       -display gtk,gl=on \
       -device virtio-balloon-pci \
       -audiodev pa,id=pa0,server=/run/user/$UID/pulse/native -device ich9-intel-hda -device hda-duplex,audiodev=pa0 \
       "$@"

使用 Intel GVT-g 的话,需要去掉 intel-iommu 那行并关掉 -vga(否则有两个显卡),然后添加:

       -device vfio-pci,sysfsdev=/sys/bus/mdev/devices/c2e3e021-95e8-46d3-929a-364708c9ebfd,display=on,x-igd-opregion=on,ramfb=on,driver=vfio-pci-nohotplug \
       -vga none \

openSUSE

准备好内核和 initrd 文件。其中 initrd 使用以下 dracut 命令生成,否则启动时没有 virtio 支持,-drive 处只能指定 if=ide

sudo dracut --add-drivers "virtio virtio_blk virtio_pci virtio_net" -N initrd-qemu

当然这样生成的 initrd 会很大。

启动系统:

#!/bin/bash -e
export LANG=en_US
unset LANGUAGE
exec qemu-system-x86_64 -enable-kvm \
       -cpu host -smp 4 \
       -drive file=/dev/sda5,format=raw,if=virtio \
       -netdev user,id=vmnic,hostname=tumbleweed \
       -device virtio-net,netdev=vmnic \
       -m 2G \
       -kernel ~/tmpfs/vmlinuz \
       -initrd ~/tmpfs/initrd-qemu \
       -append 'root=UUID=$UUID$ showopts' \
       -name "openSUSE Tumbleweed" \
       "$@"

Windows

记得加 -usb -device usb-tablet,不然鼠标只有在被捕获之后才能用。加 -rtc base=localtime 使用本地时间。

本地存储设备

指定只读使用本机磁盘设备(可用来测试启动U盘):-drive file=/dev/sdb,if=virtio,readonly

CDROM

插入与弹出光盘:[1]

(qemu) info block
(qemu) change ide2-cd0 /var/lib/libvirt/images/virtio-win.iso
(qemu) eject ide1-cd0

UEFI 启动

安装 edk2-ovmf 软件包,并复制 /usr/share/edk2-ovmf/x64/OVMF_VARS.fd 到可写的位置,然后添加参数:

  -drive if=pflash,format=raw,readonly,file=/usr/share/edk2-ovmf/x64/OVMF_CODE.fd
  -drive if=pflash,format=raw,file=./OVMF_VARS.fd

CPU

隐藏虚拟机信息:-cpu host,kvm=off,vendor=GenuineIntel,hypervisor=off

图形显示

显示方式

通过 -display 可以指定多种显示方式。

-display gtk,gl=on 使用 GTK 窗口。缩放时不会保持比例。不会拦截自身的快捷键,比如 Alt-m 会打开菜单。

-display egl-headless,gl=on,rendernode=/dev/dri/renderD128 -vnc unix:/tmp/archkde-vnc.sock:使用 VNC 连接。具体情况取决于具体的 VNC 客户端。

-display egl-headless,gl=on,rendernode=/dev/dri/renderD128 -spice unix,addr=/run/user/1000/qemu/ArchKDE/spice.sock,disable-ticketing:使用 SPICE 协议。可用客户端如 spicy

显卡设置

virtio

virtio 是一个比较好的方案,但是会比较卡顿,声音也会随着主机的视频输出变动而卡顿。虚拟机中会使用 virgl。

QXL

虚拟机中需要安装 xf86-video-qxl 驱动,并手动加载内核模块 bochs_drm。会使用 llvmpipe。要支持4K,需要增加内存:[2]

-vga none -device qxl-vga,vgamem_mb=32

Windows 的 QXL 驱动可以和 SPICE 驱动一同安装[3]

音频

使用 virtio 或者 vfio(GVT-g)视频显示时,音频可能会在视频输出有较大变化时出现卡顿。对于 Linux 系统,一种绕过的办法是,禁用声音,将音频通过网络直接传递给宿主机上的 PulseAudio 服务。

数据共享

virtiofs 文件共享

先启动服务并设置 socket 文件的权限(需要以 root 权限启动)。虚拟机里的文件权限信息会被保留。

(sleep 0.3 && setfacl -m u:lilydjwg:rwx /run/virtiofs-pacman) &
/usr/lib/qemu/virtiofsd --socket-path=/run/virtiofs-pacman -o source=/var/cache/pacman/pkg -o cache=always

然后在 qemu 命令行上指定选项[4]

  -chardev socket,id=char0,path=/run/virtiofs-pacman
  -device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=pacman
  -object memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on -numa node,memdev=mem

Windows 安装 WinFsp 之后也可以使用,见 virtio-fs - shared file system for virtual machines / Windows HowTo

virtiofs 作为根文件系统

使用 virtiofs 作为根文件系统时,可以在 Qemu 命令行上指定内核和 initramfs,如下:

  -chardev socket,id=char1,abstract=on,path=virtiofs-archkde
  -device vhost-user-fs-pci,queue-size=1024,chardev=char1,tag=root
  -object memory-backend-file,id=mem2,size=3G,mem-path=/dev/shm,share=on -numa node,memdev=mem2

  -kernel /run/ssd/archkde-rootfs/boot/vmlinuz-linux-lily
  -append 'rootfstype=virtiofs root=root rw'
  -initrd /run/ssd/archkde-rootfs/boot/initramfs-linux-lily.img

注意 virtiofs 不支持 reflink。

共享剪贴板

使用 SPICE 协议时,可以共享剪贴板。[5]设置方式如下:

  -spice unix,addr=/run/user/1000/qemu/ArchKDE/spice.sock,disable-ticketing
  -device virtio-serial-pci
  -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0
  -chardev spicevmc,id=spicechannel0,name=vdagent

webdav 共享

配置:

  -device virtserialport,chardev=spicechannel1,name=org.spice-space.webdav.0
  -chardev spiceport,id=spicechannel1,name=org.spice-space.webdav.0

虚拟机安装 phodav 软件包。webdav 位于 webdav://localhost:8943/。宿主机上默认使用 XDG「公共的」目录。[6]

USB 设备

动态添加 USB 设备

通过 lsusb 查询 USB 设备的地址,然后设置访问权限:

sudo setfacl -m u:$USER:rw /dev/bus/usb/X/Y

通过 QEMU 控制台添加与删除设备:

device_add usb-host,hostbus=X,hostaddr=Y,id=some_id
device_del some_id

接入 uas 存储设备

  -device nec-usb-xhci,id=xhci,streams=true
  -device usb-uas,id=uas,bus=xhci.0
  -device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=drive0
  -device scsi-hd,bus=uas.0,scsi-id=0,lun=1,drive=drive1
  -drive file=path/to/disk/file,if=none,format=raw,id=drive0
  -drive file=path/to/disk/file,if=none,format=raw,id=drive1

外部链接

参考资料