00 QEMU源码分析中文注释与架构讲解(v8.2.4版本)

发布于:2025-06-05 ⋅ 阅读:(29) ⋅ 点赞:(0)

QEMU-v8.2.4源码中文注释与架构讲解

文档会不定期更新

注释作者 将狼才鲸
创建日期 2025-05-30
更新日期 2025-06-02

一、前言

二、整体介绍

1、源码文件夹结构与简述

jim@virtual-pc:~/qemu$ tree -a -L 1
.
├── accel			# 硬件加速器、纯软件翻译:kvm、xen、tcg
├── audio			# 音频设备模拟
├── authz			# 授权框架,限制虚拟机对设备、API 或特定操作的访问权限
├── backends		# 后端实现:主机内存管理、TPM 后端
├── BAK_README.rst	# 原本仓库的readme文件
├── block			# 块设备:导出、IO、任务管理
├── block.c
├── blockdev.c
├── blockdev-nbd.c
├── blockjob.c
├── bsd-user		# BSD 用户模式模拟
├── chardev			# 字符设备模拟
├── common-user		# 用户模式公共代码
├── configs			# 编译相关
├── configure		# 配置脚本
├── contrib			# 社区贡献的辅助工具、脚本或第三方库
├── COPYING			# 开源信息
├── COPYING.LIB		# 开源信息相关
├── cpu-common.c	# 核心组件之一,主要负责 CPU 虚拟化的通用逻辑和基础功能实现
├── cpu-target.c	# 针对特定目标架构的 CPU 模型实现代码
├── crypto			# 加解密,数字签名
├── .dir-locals.el	# Emacs 编辑器 的本地目录变量配置文件
├── disas			# 反汇编器支持
├── docs			# 技术文档,英文的,而且对新手没什么用
├── docs_中文		# 字节写的一些中文文档
├── dump			# 系统崩溃情况下调试用
├── ebpf			# 增强 QEMU 的调试、性能分析或安全监控能力
├── .editorconfig	# 配置文件,主要用于统一代码风格和编辑器设置
├── event-loop-base.c	# 实现事件循环基础框架的核心文件
├── .exrc			# Vi/Vim 编辑器的配置文件
├── fpu				# 浮点运算库
├── fsdev			# 文件系统设备
├── .gdbinit		# 调试器相关
├── gdbstub			# GDB 调试支持
├── gdb-xml			# # 调试器相关
├── .git			# git代码管理仓库
├── .gitattributes	# git代码管理对比工具配置
├── .git-blame-ignore-revs	# git代码管理相关
├── gitdm.config	# git代码管理相关
├── .github			# git代码管理服务器相关
├── .gitignore		# git代码管理忽略的文件信息配置
├── .gitlab			# git代码管理服务器相关
├── .gitlab-ci.d	# git代码管理服务器自动测试相关
├── .gitlab-ci.yml	# git代码管理服务器自动测试相关
├── .gitmodules		# git代码管理相关
├── .gitpublish		# git代码管理相关
├── hmp-commands.hx	#  定义HMP命令的源码。HMP是一种交互式监控接口
├── hmp-commands-info.hx	# 交互式监控接口相关
├── host			# 临时构建目录
├── hw				# 所有支持的硬件设备,硬件设备模拟的核心目录,按架构与设备类型分类
├── include			# 公用头文件:硬件、核心、C标准库
├── io				# IO通道实现
├── iothread.c		# IO线程的核心实现
├── job.c			# QEMU任务的核心实现
├── job-qmp.c		# 异步任务管理的QMP接口
├── Kconfig			# 源码编译相关
├── Kconfig.host	# 源码编译相关
├── libdecnumber	# 十进制浮点数运算库
├── LICENSE			# 开源信息相关
├── linux-headers	# Linux 内核相关的头文件
├── linux-user		# Linux 用户模式模拟
├── .mailmap		# git版本管理相关
├── MAINTAINERS		# 记录代码维护者信息
├── Makefile		# 编译参数相关,顶层构建文件
├── memory_ldst.c.inc	# 内存访问操作的实现
├── meson.build		# Meson构建系统的核心配置文件
├── meson_options.txt	# 系统构建相关
├── migration		# 虚拟机迁移相关
├── module-common.c	# 模块化系统的核心实现
├── monitor			# QEMU监控器
├── nbd				# 网络块设备支持
├── net				# 网络设备模拟
├── os-posix.c		# POSIX 操作系统兼容层的实现
├── os-win32.c		# 专门为 Windows 平台实现的辅助功能模块
├── page-vary-common.c	# 动态页面大小处理 相关的核心文件
├── page-vary-target.c	# 动态页面大小处理相关
├── .patchew.yml	# 与 Patchew 系统集成的配置文件
├── pc-bios			# BIOS和固件镜像
├── plugins			# 插件支持
├── po				# 国际化i18n支持
├── python			# Python 脚本和工具
├── pythondeps.toml	# Python相关
├── qapi			# QAPI 代码生成器
├── qemu-bridge-helper.c	# 实现用户态网络桥接助手的功能
├── qemu-edid.c
├── qemu-img.c
├── qemu-img-cmds.hx
├── qemu-io.c
├── qemu-io-cmds.c
├── qemu-keymap.c
├── qemu-nbd.c
├── qemu.nsi
├── qemu-options.hx
├── qemu.sasl
├── qga				# 宿主机-虚拟机通信
├── qobject			# 基础的面向对象组件
├── qom				# QEMU 对象模型,用C语言实现面向对象
├── readme.md			# 本仓库新增的主页说明文件
├── .readthedocs.yml	# 配置RTD在线文档托管服务的配置文件
├── replay			# 执行记录和回放
├── replication.c	# 块设备复制功能的实现核心
├── roms			# ROM 镜像
├── scripts			# 源码编译相关,构建和维护脚本
├── scsi			# SCSI磁盘等设备模拟
├── semihosting		# 半主机机制
├── stats			# 代码统计和性能分析相关工具
├── storage-daemon	# 存储守护进程
├── stubs			# 桩函数
├── subprojects		# 依赖的子项目
├── system			# 系统级虚拟化(全系统模拟),也是源码主入口(main函数所在位置)
├── target			# QEMU目前所支持guset端的处理器架构,将该guest架构的指令翻译成TCG OP代码,里面的目录占源码总目的很大一部分
├── tcg				# 动态翻译工具tcg的源码部分,主要是将TCG OP转化为host binary的部分;也就是俗称的软件加速,而我们一般装Ubuntu这种大系统时需要选KVM、WHPX等硬件加速
├── tests			# 测试代码
├── tools			# 辅助工具
├── trace			# 跟踪支持
├── trace-events	# 跟踪相关
├── .travis.yml		# 配置 Travis CI(持续集成服务)的配置文件
├── ui				# 用户界面 (GTK, SDL, Cocoa 等)
├── util			# 实用工具函数
├── VERSION			# 开源信息相关
├── version.rc		# 开源信息相关
└── .vscode			# 编辑器相关

60 directories, 61 files
jim@virtual-pc:~/qemu$

2、源码入口

  • 第一行执行的代码,也就是main函数所在的位置

  • qemu-system-xxx(如-arm、-x86_64)应用程序执行的第一行代码在源码中 system/main.c 里的main()函数位置

    • 对于系统模式,main() 函数会初始化虚拟硬件,然后开始执行虚拟 CPU
    • 虚拟 CPU 初始化:target/i386/cpu.c(x86 为例)
  • 所有包含了main.c文件 + main()函数的位置:

jim@virtual-pc:~/qemu$ find . -name main.c
./contrib/ivshmem-client/main.c	# contrib是第三方库所在的文件,不算
./contrib/elf2dmp/main.c
./contrib/vhost-user-input/main.c
./contrib/rdmacm-mux/main.c
./contrib/ivshmem-server/main.c
./system/main.c			# QEMU 系统模式如qemu-system-arm程序的主入口点,负责初始化虚拟机的核心逻辑。它是模拟完整物理机器(如x86、ARM)时的关键组成部分。
./pc-bios/vof/main.c	# PowerPC(ppc64)架构相关
./pc-bios/s390-ccw/main.c
./linux-user/main.c		# 用户模式的启动入口。当运行命令如qemu-<arch> ./binary 时,程序从这里开始初始化,加载并执行目标架构的二进制文件(例如在x86主机上运行ARM程序)
./qga/main.c			# 实现客户机代理功能,即用于与宿主机端的QEMU监控程序进行通信
./bsd-user/main.c		# BSD用户模式模拟的入口点,针对的是BSD类操作系统(如FreeBSD、NetBSD、OpenBSD等)
jim@virtual-pc:~/qemu$
  • 在 system/main.c 中,main() 函数是一个简单的封装,调用 qemu_main() 函数,而后者负责实际的循环工作

    • qemu_init():负责全局初始化(如设备注册、内存管理、加速器配置等)。
    • qemu_main_loop():进入主事件循环,处理虚拟机运行逻辑。
    • qemu_cleanup():在退出时执行清理工作。
    • 解析命令行参数(如 -machine、-kernel 等),调用初始化函数
  • system/vl.c 承担核心工作

三、编译与使用

1、源码编译

jim@virtual-pc:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal
jim@virtual-pc:~$
  • 本机源码:
    • 截止到2025-06-01时的稳定版分支v8.2.4的源码
      • 如果你不介意版本是否稳定,也可以直接在v9.0.0 tag的基础上进行修改;
      • QEMU官网虽然已经能下载v10.0.2和v9.2.4的软件了,但是源码仓库里还没有这2个标签,并且官网源码的最后上传时间是一年前。

2024-05-13 08:29 +0300 Michael Tokarev o─{origin/stable-8.2} {origin/staging-8.2} <v8.2.4> Update version for 8.2.4 release

  • 编译过程:

  • 1、提前修改编译过程中需要联网拉取的gitlab.com网站中的子git仓库的国内Gitee源(本仓库内我已修改好了,请在本文章最上方的Gitee源码链接下拉取改好的QEMU仓库)

    • 如果你能登上gitlab.com,则请忽略此步骤;
    • 如果你没使用梯子,则编译配置时需要拉取源码,然后因为gitlab网站被墙导致失败;
    • 具体需要的子仓库是:gitlab.com/qemu-project/seabios.git SLOF.git ipxe.git openbios.git qemu-palcode.git u-boot.git skiboot.git QemuMacDrivers.git seabios-hppa.git u-boot-sam460ex.git edk2.git opensbi.git qboot.git vbootrom.git libvirt-ci.git
    • 自行修改的方法1:
      • 把QEMU仓库里的所有 https://gitlab.com/qemu-project/ 字符串替换为 https://gitee.com/tinylab/qemu-
    • 自行修改的方法2:
      • 主要是.gitmodules文件中、subprojects/ 文件夹下、tests/文件夹下的非gitlab.com/qemu-project/qemu.git 部分不替换会出错(编译时qemu.git源码我们肯定已经拉取了,是其它仓库造成的编译时预配置不通过),子模块拉不下来;
      • 将 .gitmodules 文件中所有 gitlab.com/qemu-project/ 替换成 gitee.com/tinylab/qemu-
      • 将 subprojects\ 文件夹下所有 .wrap 文件中的 gitlab.com/qemu-project/ 替换成 gitee.com/tinylab/qemu-
        • 具体包括:
        • subprojects\keycodemapdb.wrap
        • subprojects\berkeley-softfloat-3.wrap
        • subprojects\dtc.wrap
        • subprojects\libvfio-user.wrap
      • 将 tests\ 文件夹下所有 .wrap 文件中的 gitlab.com/qemu-project/ 替换成 gitee.com/tinylab/qemu-
        • 具体包括:
        • tests\avocado\acpi-bits.py
        • tests\qtest\fuzz-lsi53c895a-test.c
        • tests\qtest\fuzz-megasas-test.c
        • tests\qtest\fuzz-sdcard-test.c
        • tests\qtest\intel-hda-test.c
        • tests\tcg\aarch64\mte-7.c
        • tests\tcg\aarch64\test-2150.c
        • tests\tcg\aarch64\test-2248.c
      • 如果上述国内镜像仓库也失效的话,则在Gitee网站搜索 qemu-project ,再换一个好心人提供的国内源
  • 你也可以试着先把全部代码拉下来,或者找到完整的国内镜像源,预先从外网拉取全量代码的步骤如下:

    • git clone https://gitlab.com/qemu-project/qemu.git
    • cd qemu
    • git submodule init
    • git submodule update --recursive
  • 2、因少数非关键国内源子仓库版本不匹配,编译不通过,需要修改 tests\fp\meson.build 文件

    • (本仓库内我已修改好了,请在本文章最上方的Gitee源码链接下拉取改好的QEMU仓库)
    • 如果你能登上gitlab.com,则请忽略此步骤;
    • 国内镜像子仓库里源码版本的同步时间不是我当前时间,和qemu-project中的实际仓库的内容不同步,我这里遇到的是berkeley-testfloat-3.git编译报错
    • 将 tests\fp\meson.build 文件中第32行到35行、第47到52行、第108到源码最后的143行前面加上#井号来屏蔽脚本
    • 这部分内容本来也是测试用例,删掉不影响实际使用
  • 3、更新软件包索引

    • sudo apt update
  • 4、安装编译时依赖的软件和库(必须要先装)

    • sudo apt install gcc make python3-venv python3-pip ninja-build libglib2.0-dev flex bison libcapstone-dev libfdt-dev device-tree-compiler
  • 5、使用python环境安装软件包

    • pip3 install Sphinx sphinx_rtd_theme
  • 6、进行编译前的配置:

    • cd ~/qemu# 进入源码目录
    • mkdir build
    • cd build
    • ../configure# 配置为全部目标进行编译
    • 以下是执行过程:
jim@virtual-pc:~$ cd ~/qemu
jim@virtual-pc:~/qemu$ mkdir build
jim@virtual-pc:~/qemu$ cd build
jim@virtual-pc:~/qemu/build$ ../configure
python determined to be '/usr/bin/python3'
python version: Python 3.8.10
mkvenv: Creating non-isolated virtual environment at 'pyvenv'
mkvenv: checking for tomli>=1.2.0
mkvenv: installing tomli>=1.2.0
mkvenv: checking for meson>=0.63.0
mkvenv: installing meson==1.2.3
mkvenv: checking for sphinx>=1.6
mkvenv: checking for sphinx_rtd_theme>=0.5
The Meson build system
……
  Subprojects
    berkeley-softfloat-3                         : YES
    keycodemapdb                                 : YES
    libvduse                                     : YES
    libvhost-user                                : YES

  User defined options
    Native files                                 : config-meson.cross
    docs                                         : enabled
    plugins                                      : true

Found ninja-1.10.0 at /usr/bin/ninja
Running postconf script '/home/jim/qemu/build/pyvenv/bin/python3 /home/jim/qemu/scripts/symlink-install-tree.py'
jim@virtual-pc:~/qemu/build$
  • 因为我只需要32位ARM平台的工具,所以我实际使用的命令是:../configure --target-list=arm-softmmu,arm-linux-user

  • 7、编译:

    • make -j4# 使用4进程编译;你的电脑是几核就配成几,也可以多配
jim@virtual-pc:~/qemu/build$ make -j4
[1/52] Generating tests/include/QAPI test (include) with a custom command
[2/20] Generating qemu-version.h with a custom command (wrapped by meson to capture output)
jim@virtual-pc:~/qemu/build$
  • 8、将编译好的 qemu-system-arm 等应用程序安装到Ubuntu系统内:
    • sudo make install
jim@virtual-pc:~/qemu/build$ sudo make install
[1/20] Generating qemu-version.h with a custom command (wrapped by meson to capture output)
[1/2] Installing files.
Installing subdir /home/jim/qemu/build/docs/manual to /usr/local/share/doc/qemu
……
Installing /home/jim/qemu/pc-bios/keymaps/sv to /usr/local/share/qemu/keymaps
jim@virtual-pc:~/qemu/build$
  • 9、测试程序的使用(查看版本号):
    • qemu-system-arm --version
jim@virtual-pc:~/qemu/build$ qemu-system-arm --version
QEMU emulator version 8.2.4 (v8.2.4-9-g953cc60a63-dirty)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
jim@virtual-pc:~/qemu/build$

2、使用1:QEMU安装并运行虚拟机

3、使用2:直接运行目标平台程序

  • 我编译生成的是32位ARM平台的QEMU,所以我不能直接在Ubuntu上使用GCC编译程序后再在QEMU中运行运行,而需要使用ARM交叉编译工具编完后再用qemu-system-arm来运行;

  • ARM交叉编译工具介绍:

交叉编译工具名 目的
arm-none-eabi-gcc 供裸机如Cortex-M3板子使用,不能使用fork()等系统类函数,不能编Linux应用
arm-linux-gnueabi-gcc 用于编译u-boot、Linux内核、linux应用,支持armel软浮点,32位
arm-linux-gnueabihf-gcc 支持armhf硬浮点,64位
arm-eabi-gcc Android ARM 编译器
armcc 供Keil使用,编译裸机程序,不能编译Linux应用
arm-none-uclinuxeabi-gcc 用于其它系统:uCLinux
arm-none-symbianelf-gcc 用于其它系统:symbian
带芯片厂商名字或由芯片厂商单独提供 芯片原厂基于上述源码定制的交叉编译工具
  • 1)安装32位ARM交叉编译工具:

    • sudo apt install gcc-arm-linux-gnueabi
  • 2)查看安装结果

    • arm-linux-gnueabi-gcc --version
jim@virtual-pc:~/qemu$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jim@virtual-pc:~/qemu$
  • 3)编译要测试的程序

    • cd ~/qemu# 进入源码目录
    • mkdir demo
    • cd demo
    • touch main.c# 创建源码文件
    • gedit main.c
  • main.c文件中加入内容:

#include <stdio.h>

int main()
{
	printf("Hello World!\n");
	fflush(stdout);

	while(1);

	return 0;
}
  • 继续:
    • arm-linux-gnueabi-gcc -o hello main.c -static# 编译生成hello程序(必须使用静态库)
    • file hello # 查看架构是否正确
      • jim@virtual-pc:~/qemu/demo$ file hello
      • hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, BuildID[sha1]=e02cd9a7928171b8c7631f7ef83182807a45ccf4, for GNU/Linux 3.2.0, not stripped
    • qemu-arm hello# 使用qemu运行程序
      • jim@virtual-pc:~/qemu/demo$ qemu-arm hello
      • Hello World!
    • 不能使用运行操作系统镜像的qemu-system-arm程序:
jim@virtual-pc:~/qemu/demo$ qemu-system-arm -machine raspi2b hello
WARNING: Image format was not specified for 'hello' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
qemu-system-arm: Invalid SD card size: 509 KiB
SD card size has to be a power of 2, e.g. 512 KiB.
You can resize disk images with 'qemu-img resize <imagefile> <new-size>'
(note that this will lose data if you make the image smaller than it currently is).

4、修改源码,并查看是否生效

  • 1)在system/main.c文件的main()函数中加入一行:
    • printf("(build time: %s %s, for system)main entry: file: %s, line: %d\n", __DATE__, __TIME__, __FILE__, __LINE__);
  • 2)进入qemu/build目录执行make命令
jim@virtual-pc:~/qemu/build$ make
/home/jim/qemu/build/pyvenv/bin/meson introspect --targets --tests --benchmarks | /home/jim/qemu/build/pyvenv/bin/python3 -B scripts/mtest2make.py > Makefile.mtest
[1/53] Generating qemu-version.h with a custom command (wrapped by meson to capture output)
[2/50] Compiling C object qemu-system-arm.p/system_main.c.o
[3/50] Linking target qemu-system-arm
[4/50] Compiling C object libqemu-arm-linux-user.fa.p/linux-user_main.c.o
[5/50] Linking target qemu-arm
[6/50] Compiling C object qga/qemu-ga.p/main.c.o
[7/50] Linking target qga/qemu-ga
[8/50] Compiling C object qemu-img.p/qemu-img.c.o
[9/50] Linking target qemu-img
[10/50] Compiling C object qemu-io.p/qemu-io.c.o
[11/50] Linking target qemu-io
[12/50] Compiling C object qemu-nbd.p/qemu-nbd.c.o
[13/50] Linking target qemu-nbd
[14/50] Compiling C object storage-daemon/qemu-storage-daemon.p/qemu-storage-daemon.c.o
[15/50] Linking target storage-daemon/qemu-storage-daemon
[16/50] Compiling C object qemu-pr-helper.p/scsi_qemu-pr-helper.c.o
[17/50] Linking target qemu-pr-helper
[18/50] Generating tests/include/QAPI test (include) with a custom command
jim@virtual-pc:~/qemu/build$

jim@virtual-pc:~/qemu/build$ find . -name qemu-system-arm
./arm-softmmu/qemu-system-arm
./qemu-system-arm
./qemu-bundle/usr/local/bin/qemu-system-arm
jim@virtual-pc:~/qemu/build$ ls ./arm-softmmu/qemu-system-arm -l
lrwxrwxrwx 1 jim jim 18 61 20:16 ./arm-softmmu/qemu-system-arm -> ../qemu-system-arm
jim@virtual-pc:~/qemu/build$ ls ./qemu-bundle/usr/local/bin/qemu-system-arm -l
lrwxrwxrwx 1 jim jim 36 61 00:16 ./qemu-bundle/usr/local/bin/qemu-system-arm -> /home/jim/qemu/build/qemu-system-arm
jim@virtual-pc:~/qemu/build$ ls -l ./qemu-system-arm
-rwxrwxr-x 1 jim jim 115438744 62 13:21 ./qemu-system-arm
jim@virtual-pc:~/qemu/build$
  • 3)运行你刚刚生成的./qemu-system-arm --version查看效果
    • 这一行命令的执行需要在qemu/build目录下
    • 这一行内容的实际信息也能防止你改完源码后没运行到刚刚编译的程序,实际运行了已安装在系统中的旧程序;
jim@virtual-pc:~/qemu/build$ ./qemu-system-arm --version
(Jun  2 2025 13:21:18)main entry: file: ../system/main.c, line: 53
QEMU emulator version 8.2.4 (v8.2.4-13-g8fdc46628f-dirty)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
jim@virtual-pc:~/qemu/build$
  • 4)或者修改linux-user/main.c文件,之后用qemu-arm --version来验证是否生效
jim@virtual-pc:~/qemu/build$ make
[1/19] Generating qemu-version.h with a custom command (wrapped by meson to capture output)
[2/3] Compiling C object libqemu-arm-linux-user.fa.p/linux-user_main.c.o
[3/3] Linking target qemu-arm
jim@virtual-pc:~/qemu/build$ ls -l qemu-arm
-rwxrwxr-x 1 jim jim 25443984 62 13:41 qemu-arm
jim@virtual-pc:~/qemu/build$ ./qemu-arm --version
(build time: Jun  2 2025 13:41:49, for user bin)main entry: file: ../linux-user/main.c, line: 689
qemu-arm version 8.2.4 (v8.2.4-13-g8fdc46628f-dirty)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
jim@virtual-pc:~/qemu/build$

四、源码整体框架讲解

五、各子模块讲解

六、实战:加入一款芯片的模拟器功能


网站公告

今日签到

点亮在社区的每一天
去签到