4. QEMU基础与安装
好,咱们进入实战环节。这一章的目标很明确——从源码把QEMU RISC-V模拟器编译出来,装到你的机器上。别小看这一步,很多人在后面联调时遇到诡异问题,回头一查,往往是编译时少配了一个目标架构。
我个人习惯把QEMU源码编译分成四个阶段:下载 → 配置 → 编译 → 安装验证。下面咱们一步步走。
4.1 下载QEMU源码
QEMU官方源码托管在GitLab上。我建议你直接拉取稳定分支,别用master——master天天在变,今天编译通过,明天可能就挂了。
推荐方式:使用git clone,方便后续切换版本或打补丁。
# 克隆QEMU官方仓库
git clone https://gitlab.com/qemu-project/qemu.git
cd qemu
# 切换到最新的稳定分支(以v8.2.0为例)
git checkout stable-8.2
# 或者直接打tag
git checkout v8.2.0
如果你网络不好,也可以去 https://download.qemu.org/ 下载tar.xz压缩包。但我还是推荐git方式——你想想看,后面调试时如果需要回退版本,git checkout一下就搞定,省事多了。
小技巧:下载完成后,先看一眼 git log --oneline -5,确认你确实在目标版本上。我曾经有一次忘了切分支,在master上编译了半天,结果发现RISC-V的某些特性还没合入……
4.2 配置RISC-V目标支持
配置这一步,说白了就是告诉QEMU的构建系统:我要编译哪些东西。QEMU支持几十种架构,你全编的话,机器能跑半小时以上。咱们只编RISC-V相关的。
QEMU使用 configure 脚本进行配置。它和Linux内核的配置思路类似,但更简洁。
4.2.1 安装依赖包
在配置之前,先把编译工具链和依赖装上。不同发行版命令略有不同:
| 发行版 | 安装命令 |
|---|---|
| Ubuntu/Debian | sudo apt install build-essential pkg-config libglib2.0-dev libpixman-1-dev libslirp-dev |
| Fedora/RHEL | sudo dnf install gcc glib2-devel pixman-devel libslirp-devel |
| Arch Linux | sudo pacman -S base-devel glib2 pixman libslirp |
注意:libslirp是网络后端支持,如果你不装,后面用-user模式网络时会报错。我刚开始就漏了这个,折腾了半小时才发现。
4.2.2 执行configure
配置命令如下。咱们只开启RISC-V目标,同时启用一些常用特性:
mkdir build && cd build
../configure \
--target-list=riscv32-softmmu,riscv64-softmmu \
--enable-slirp \
--enable-kvm \
--enable-debug \
--prefix=/opt/qemu-riscv
解释一下这几个选项:
- --target-list:指定要编译的目标架构。这里只编RISC-V 32位和64位的完整系统模拟(softmmu)。
- --enable-slirp:启用用户态网络栈,方便后面做网络联调。
- --enable-kvm:开启KVM加速支持。虽然RISC-V的KVM支持还在完善中,但先开上没坏处。
- --enable-debug:保留调试符号。编译出来的体积会大一些,但后面调试固件时能省很多时间。
- --prefix:安装路径。我习惯单独放一个目录,不和系统自带的QEMU冲突。
核心要点:如果你只做RISC-V开发,--target-list 里只写 riscv32-softmmu,riscv64-softmmu 就够了。别贪多,编译时间能缩短70%以上。
配置完成后,终端会输出一份摘要。我建议你仔细看一眼,确认 RISC-V 出现在目标列表中。嗯,这一步虽然简单,但很多人在这里翻车——配了但没完全配。
4.3 编译与安装
配置没问题,接下来就是编译。QEMU的编译系统基于GNU Make,直接跑 make 就行。
4.3.1 编译
# 使用4个并行任务编译,根据你的CPU核心数调整
make -j$(nproc)
第一次编译会比较慢,大概5~15分钟,取决于你的机器性能。这时候可以去泡杯咖啡。
避坑指南:如果编译过程中报错,先检查依赖包是否装全。最常见的错误是 glib-2.0 或 pixman-1 找不到。我曾经在CentOS 7上遇到过glib版本太老的问题,最后手动升级才搞定。
4.3.2 安装
编译完成后,执行安装:
sudo make install
安装到 /opt/qemu-riscv 目录下。你可以看看里面都有什么:
ls /opt/qemu-riscv/bin/
# 输出示例:
# qemu-system-riscv32 qemu-system-riscv64 qemu-system-riscv64-linux-user
看到 qemu-system-riscv32 和 qemu-system-riscv64 这两个可执行文件,说明安装成功。
4.3.3 知识结构图
下面这张图总结了从下载到安装的完整流程,以及每个阶段的关键产出物:
4.4 验证QEMU RISC-V模拟器
安装完了,怎么知道它能不能用?别急,咱们跑几个简单的验证命令。
4.4.1 检查版本与目标列表
/opt/qemu-riscv/bin/qemu-system-riscv64 --version
# 输出示例:
# QEMU emulator version 8.2.0
# Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
看到版本号,说明可执行文件没问题。接下来确认它支持RISC-V:
/opt/qemu-riscv/bin/qemu-system-riscv64 -M help
这条命令会列出所有支持的RISC-V机器类型。你应该能看到类似这样的输出:
Supported machines are:
none empty machine
sifive_e RISC-V Board compatible with SiFive E SDK
sifive_u RISC-V Board compatible with SiFive U SDK
spike RISC-V Spike board (default)
virt RISC-V VirtIO board
...
看到 virt 和 spike 这两个板子,基本就稳了。咱们后面联调主要用 virt 板。
4.4.2 快速启动测试
为了验证模拟器能真正跑起来,咱们用QEMU内置的BIOS(OpenSBI)启动一下:
/opt/qemu-riscv/bin/qemu-system-riscv64 \
-M virt \
-m 256M \
-nographic \
-bios none
这条命令会启动一个不带固件的RISC-V虚拟机。因为没有引导程序,QEMU会停在ROM里,终端上会看到类似 QEMU: waiting for a reset 的提示。按 Ctrl+A 然后 X 退出。
验证通过的标准:QEMU进程能正常启动、不报错、能响应退出命令。这就说明你的RISC-V模拟器已经可以用了。
4.4.3 验证清单
我把验证步骤整理成了一张表,方便你对照检查:
| 验证项 | 命令 | 预期结果 |
|---|---|---|
| 版本检查 | qemu-system-riscv64 --version |
显示QEMU版本号 |
| 目标列表 | qemu-system-riscv64 -M help |
列出virt、spike等机器类型 |
| 最小启动 | qemu-system-riscv64 -M virt -m 256M -nographic -bios none |
QEMU启动不报错,可正常退出 |
| 32位支持 | qemu-system-riscv32 -M help |
同样列出RISC-V 32位机器类型 |
个人经验:验证时别忘了测一下32位的模拟器。很多人在64位上跑通了,换到32位就出问题。我遇到过glib版本不兼容导致32位模拟器段错误的情况,提前测一下能省不少排查时间。
4.5 常见问题与解决
编译安装过程中,你可能会遇到下面几个问题。我把它们列出来,方便你对照排查:
- configure报错:glib-2.0 not found —— 安装
libglib2.0-dev(Ubuntu)或glib2-devel(Fedora)。 - make报错:undefined reference to `slirp_*' —— 安装
libslirp-dev,然后重新configure。 - qemu-system-riscv64: command not found —— 检查
--prefix路径是否在PATH环境变量中。可以加个软链接或直接使用绝对路径。 - 启动时卡在 "No boot device" —— 这是正常的,因为还没给固件。后面章节会教你怎么加载固件。
重要提醒:如果你在编译过程中修改了configure选项,一定要先 make clean 再重新编译。我见过有人直接重新configure然后make,结果新旧目标混在一起,链接出一堆奇怪错误。