40 使用快速模拟器(QEMU)

Yocto Project 将开源项目 Quick EMUlator(QEMU)的一种实现纳入开发工具集。 本章介绍 QEMU 的使用步骤,以及有助于开发的其他信息。

40 概述

在 Yocto Project 中,QEMU 是模拟器和虚拟机,可让使用 Yocto Project 构建的 完整镜像像普通任务一样运行在构建系统上。它可以在没有实际硬件的情况下, 运行和测试受支持架构的镜像及应用程序。Yocto Project 还使用 QEMU 对每次 发行的最终镜像执行自动化质量保证(QA)测试等工作。

备注

此实现与通用 QEMU 并不完全相同。

本节为 Yocto Project 中的 QEMU 实现提供简要参考。

通用 QEMU 的官方信息和文档见:

40 运行 QEMU

使用 QEMU 前,需要安装并初始化 QEMU,准备好对应产物,即镜像文件和根文件 系统。基本步骤如下:

  1. 安装 QEMU: Yocto Project 提供多种获取 QEMU 的方式,其中之一是安装 软件开发工具包(SDK)。安装方法见 Yocto Project 应用程序开发与可扩展 软件开发工具包(eSDK)手册的 “QEMU 模拟器” 一节。

  2. 设置环境: QEMU 环境设置方式取决于安装方法:

    • 如果按 准备使用 Yocto Project 操作,可使用 bitbake-setup,或 手动加载环境设置脚本:

      $ cd bitbake-builds
      $ source layers/openembedded-core/oe-init-build-env
      
    • 如果安装了交叉工具链,可运行工具链初始化脚本。例如,以下命令运行 默认 poky_sdk 目录中的脚本:

      . poky_sdk/environment-setup-core2-64-poky-linux
      
  3. 确保产物就绪: 需要能够在 QEMU 中启动的预构建内核,以及适合目标 机器架构的根文件系统:

    • 如果已为 QEMU 构建过镜像,例如 qemux86、qemuarm,产物已经 位于 Build Directory。

    • 如果尚未构建镜像,可以到 machines/qemu 下载与架构匹配且可在 QEMU 中运行的预构建镜像。

    提取根文件系统的方法,见 Yocto Project 应用程序开发与可扩展软件开发 工具包(eSDK)手册的 “解压根文件系统” 一节。

  4. 运行 QEMU: runqemu 的基本语法如下:

    $ runqemu [option ] [...]
    

    runqemu 会根据命令行参数推断所需操作。例如,需要查找镜像时,默认 按时间戳选择最近构建的镜像。至少需要通过选项提供机器名称、虚拟机镜像 (*wic.vmdk)或内核镜像(*.bin)之一。

    以下示例进一步说明用法:

    • 本例以 MACHINE="qemux86-64" 启动 QEMU。在标准 Build Directory 下,runqemu 自动找到 bzImage-qemux86-64.bin 和 core-image-minimal-qemux86-64-20200218002850.rootfs.ext4,假定当前 构建生成的是 core-image-minimal 镜像:

      $ runqemu qemux86-64
      

      备注

      如果有多个同名镜像,QEMU 按时间戳选择最近构建的镜像。

    • 以下命令与上例结果相同,但显式指定镜像及根文件系统类型:

      $ runqemu qemux86-64 core-image-minimal ext4
      
    • 本例使用临时根文件系统("snapshot"),不启用图形界面("nographic"), 因而直接在当前 Shell 中启动 QEMU:

      $ runqemu qemux86-64 snapshot nographic
      

      "snapshot" 模式下,退出 QEMU 后不会保留根文件系统的修改。

    • 本例启动 Initramfs 镜像,并启用 QEMU 音频。此时 runqemu 将内部变量 FSTYPE 设为 cpio.gz。启用音频还需安装适当驱动, 详见 runqemu 命令行选项 的 audio 选项:

      $ runqemu qemux86-64 ramfs audio
      
    • 本例信息不足,无法启动 QEMU。虽然提供了根文件系统类型,但还必须至少 提供 MACHINE、KERNEL 或 VM 选项之一:

      $ runqemu ext4
      
    • 本例启动虚拟机镜像(.wic.vmdk 文件)。runqemu 从文件名判断 QEMU 架构(MACHINE)为 "qemux86-64",根文件系统类型为 "vmdk":

      $ runqemu /home/scott-lenovo/vm/core-image-minimal-qemux86-64.wic.vmdk
      

40 切换控制台

QEMU 启动或运行期间,可按 Ctrl+Alt+数字切换受支持的控制台。例如,如果 串口控制台已启用,Ctrl+Alt+3 可切换过去。主 QEMU 控制台因故障无法使用时, 这种切换能力很有帮助。

备注

通常,"2" 对应主控制台,"3" 对应串口控制台。

40 移除启动画面

QEMU 启动时可按 Alt+左方向键移除启动画面,查看后台正在发生的事情。

40 禁用鼠标捕获

默认 QEMU 集成会将鼠标指针限制在主窗口内,因为标准鼠标设备只提供相对输入, 不提供绝对坐标。此时需要按 "Ctrl+Alt" 释放指针。Yocto Project 的 QEMU 集成默认启用 wacom USB 触控板驱动,支持绝对坐标输入,因此鼠标可以自由 进出主窗口,不会被捕获,使用体验更好。

40 通过网络文件系统(NFS)服务器运行

可以通过 NFS 服务器运行 QEMU。当构建系统和模拟系统需要同时访问同一文件 系统时,这种方式很有用。它使用用户空间 NFS 服务器,因此不需要 root 权限。设置步骤如下。

  1. 提取根文件系统: 环境能够运行 QEMU 后,可以使用与 runqemu 同在 scripts 目录中的 runqemu-extract-sdk 脚本。

    此脚本将根文件系统归档包提取到指定位置。以下示例提取到 test-nfs 目录:

    runqemu-extract-sdk ./tmp/deploy/images/qemux86-64/core-image-sato-qemux86-64.tar.bz2 test-nfs
    
  2. 启动 QEMU: 提取完成后,正常运行 runqemu,额外指定文件系统位置。 此后修改 ./test-nfs 中的文件,会实时反映到镜像中。以下示例使用 qemux86 镜像:

    runqemu qemux86-64 ./test-nfs
    

备注

如需启动、停止或重启 NFS 共享,可以使用以下命令:

  • 启动 NFS 共享:

    runqemu-export-rootfs start file-system-location
    
  • 停止 NFS 共享:

    runqemu-export-rootfs stop file-system-location
    
  • 重启 NFS 共享:

    runqemu-export-rootfs restart file-system-location
    

40 KVM 下的 QEMU CPU 兼容性

默认情况下,QEMU 构建面向 64 位 x86 Intel Core2 Duo 和 32 位 x86 Intel Pentium II 处理器。选择这些 CPU 类型,是因为其特性与许多常用 CPU 有广泛 兼容性。

即使兼容范围很广,这些 CPU 仍可能支持主机 CPU 不具备的特性。QEMU 软件 模拟时通常没有问题,但启用 KVM 后可能出错:针对某项 CPU 特性编译的软件, 在不支持该特性的 KVM CPU 上运行会崩溃。可以修改 Build Directory 的 deploy/image 目录中 qemuboot.conf 的 QB_CPU_KVM,覆盖 QEMU 运行时 CPU 设置。该值决定 runqemu 传给 QEMU 的 -cpu 选项。运行 qemu -cpu help 可查看支持的 CPU 类型。

40 QEMU 性能

模拟速度取决于目标与主机架构的组合。例如,在 Intel 32 位 x86 主机上运行 qemux86 镜像较快,因为架构一致;同一主机运行 qemuarm 则可能较慢, 但仍能准确模拟 ARM 特有的问题。

为加快速度,QEMU 镜像支持通过 distcc 调用模拟系统之外的交叉编译器。 如果由 runqemu 启动,且主机有 distccd,在 QEMU 中调用 distcc 即可自动使用构建系统提供的 BitBake 交叉编译工具链。可通过设置编译器变量 实现,例如 export CC="distcc"。如果使用合适的 SDK 镜像或存在适当的 独立工具链,也会自动使用该工具链。

备注

有几种方式连接 QEMU 中运行的系统:

  • QEMU 提供帧缓冲接口,可使用标准控制台。

  • 无显示器的嵌入式设备通常有串口,可以配置镜像的操作系统,通过串口 运行控制台。连接使用标准 IP 网络。

  • 部分 QEMU 镜像包含 SSH 服务器。core-image-sato 提供禁用 root 密码的 Dropbear SSH 服务器,core-image-full-cmdline 使用 OpenSSH。 这些服务器支持标准 ssh 和 scp 命令。core-image-minimal 则不包含 SSH 服务器。

  • 可以使用所提供的用户空间 NFS 服务器,通过主机上的本地根文件系统 副本启动 QEMU。先用 runqemu-extract-sdk 提取根文件系统归档包, 再让 runqemu 指向提取目录,而非根文件系统镜像文件。详见 “通过网络文件系统(NFS)服务器运行” 一节。

40 QEMU 命令行语法

runqemu 的基本语法如下:

$ runqemu [option ] [...]

runqemu 根据命令行参数推断所需操作。例如,需要查找镜像时,默认按 时间戳选择最近构建的镜像。至少需要提供机器名称、虚拟机镜像(*wic.vmdk) 或内核镜像(*.bin)之一。

以下为 runqemu 的命令行帮助输出:

$ runqemu --help

Usage: you can run this script with any valid combination
of the following environment variables (in any order):
  KERNEL - the kernel image file to use
  ROOTFS - the rootfs image file or nfsroot directory to use
  MACHINE - the machine name (optional, autodetected from KERNEL filename if unspecified)
  Simplified QEMU command-line options can be passed with:
    nographic - disable video console
    serial - enable a serial console on /dev/ttyS0
    slirp - enable user networking, no root privileges required
    kvm - enable KVM when running x86/x86_64 (VT-capable CPU required)
    kvm-vhost - enable KVM with vhost when running x86/x86_64 (VT-capable CPU required)
    publicvnc - enable a VNC server open to all hosts
    audio - enable audio
    [*/]ovmf* - OVMF firmware file or base name for booting with UEFI
  tcpserial=<port> - specify tcp serial port number
  biosdir=<dir> - specify custom bios dir
  biosfilename=<filename> - specify bios filename
  qemuparams=<xyz> - specify custom parameters to QEMU
  bootparams=<xyz> - specify custom kernel parameters during boot
  help, -h, --help: print this text

Examples:
  runqemu
  runqemu qemuarm
  runqemu tmp/deploy/images/qemuarm
  runqemu tmp/deploy/images/qemux86/<qemuboot.conf>
  runqemu qemux86-64 core-image-sato ext4
  runqemu qemux86-64 wic-image-minimal wic
  runqemu path/to/bzImage-qemux86.bin path/to/nfsrootdir/ serial
  runqemu qemux86 iso/hddimg/wic.vmdk/wic.qcow2/wic.vdi/ramfs/cpio.gz...
  runqemu qemux86 qemuparams="-m 256"
  runqemu qemux86 bootparams="psplash=false"
  runqemu path/to/<image>-<machine>.wic
  runqemu path/to/<image>-<machine>.wic.vmdk

40 runqemu 命令行选项

命令行可用的 runqemu 选项如下:

备注

如果提供的选项组合无效或信息不足,runqemu 会给出相应错误消息, 帮助修正问题。

  • QEMUARCH:QEMU 机器架构,必须是 "qemuarm"、"qemuarm64"、"qemumips"、 "qemumips64"、"qemuppc"、"qemux86" 或 "qemux86-64"。

  • VM:虚拟机镜像,必须为 .wic.vmdk 文件。启动该格式镜像时使用。

  • ROOTFS:根文件系统,扩展名为 "ext2"、"ext3"、"ext4"、"jffs2"、 "nfs" 或 "btrfs"。使用 "nfs" 时必须明确指定根文件系统路径。

  • KERNEL:内核镜像,即 .bin 文件。提供 .bin 时,runqemu 将其识别为内核镜像。

  • MACHINE:QEMU 机器架构,必须为 "qemux86"、"qemux86-64"、"qemuarm"、 "qemuarm64"、"qemumips"、"qemumips64" 或 "qemuppc"。MACHINE 与 QEMUARCH 基本相同。未提供 MACHINE 时,runqemu 尝试根据其他选项判断。

  • ramfs:启动 Initramfs 镜像,即 FSTYPE 为 cpio.gz。

  • iso:启动 ISO 镜像,即 FSTYPE 为 .iso。

  • nographic:禁用视频控制台,将控制台设为 "ttys0"。登录服务器且不希望 禁用 X Window System(X11)向工作站或笔记本转发时,此选项很有用。

  • serial:在 /dev/ttyS0 启用串口控制台。

  • biosdir:指定 BIOS、VGA BIOS 和键盘映射的自定义目录。

  • biosfilename:指定自定义 BIOS 名称。

  • qemuparams=\"xyz\":指定自定义 QEMU 参数,可传入简单的 "kvm" 和 "serial" 以外的选项。

  • bootparams=\"xyz\":指定自定义内核启动参数。

  • audio:启用 QEMU 音频。MACHINE 必须为 "qemux86" 或 "qemux86-64", 且 Linux 来宾中安装 snd_intel8x0 或 snd_ens1370 驱动。

  • slirp:启用 "slirp" 网络。这种网络方式不需要 root 权限,但易用性 和完整性不如默认方式。

    slirp 默认将来宾 TCP 22 和 23 端口转发到主机 2222 和 2323 端口, 或下一个空闲端口。可通过环境变量 QB_SLIRP_OPT,或 Build Directory 的 deploy/image 中 qemuboot.conf 设置 特定转发规则。例如:

    QB_SLIRP_OPT = "-netdev user,id=net0,hostfwd=tcp::8080-:80"
    
    QB_SLIRP_OPT = "-netdev user,id=net0,hostfwd=tcp::8080-:80,hostfwd=tcp::2222-:22"
    

    第一个示例将模拟系统 TCP 80 端口转发到主机 8080 或下一个空闲端口, 可通过 http://<host ip>:8080/ 访问 QEMU 内的 HTTP 服务器。

    第二个示例还将来宾 TCP 22 端口转发到主机 2222 或下一个空闲端口, 可通过 ssh -P 2222 <user>@<host ip> SSH 登录模拟系统。

    请确保正确配置防火墙软件。

  • kvm:为 "qemux86" 或 "qemux86-64" 启用 KVM,必须满足:

    • MACHINE 为 "qemux86" 或 "qemux86-64"。

    • 构建主机已安装 KVM 模块,提供 /dev/kvm。

    • 构建主机上的 /dev/kvm 可读写。

  • kvm-vhost:为 "qemux86" 或 "qemux86-64" 启用带 VHOST 支持的 KVM, 必须满足:

    • 满足上述 kvm 选项条件。

    • 构建主机具有 virtio 网络设备 /dev/vhost-net。

    • 构建主机上的 /dev/vhost-net 可读或可写,并启用了 slirp。

  • publicvnc:启用向所有主机开放的 VNC 服务器。