:从 QAPI 单一事实源自动生成的机器接口全量指南)
QEMU QMP 参考手册qemu-qmp-ref从 QAPI 单一事实源自动生成的机器接口全量指南【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址: https://gitcode.com/gh_mirrors/qe/qemu导读本文围绕 QEMU 官方文档中的 docs/interop/qemu-qmp-ref.rst即“QEMU QMP Reference Manual”展开说明这份参考手册的本质它不是一个手写文档而是 Sphinx 构建系统在编译时从 QAPI 模式schema中自动提取全部命令、事件、类型注释并生成的一份“机器可读接口字典”。读完本文你将掌握QMP 参考手册的生成机制与构建方法、如何从 qapi/qapi-schema.json 追溯到任意命令的权威定义、QMP 会话的基本交互流程握手、能力协商、查询与内省以及如何把这份手册用于开发你自己的 QEMU 管理程序。一、这份文档到底是什么一个“活”的参考手册打开 docs/interop/qemu-qmp-ref.rst全文只有 10 行左右.. _QMP Ref: QEMU QMP Reference Manual .. contents:: :local: .. qapi-doc:: qapi/qapi-schema.json :namespace: QMP这并非文档残缺而是 QEMU 文档体系中的刻意设计参考类文档一律采用“占位 指令”的方式真正的正文全部存放在 QAPI 模式文件里构建时由 Sphinx 扩展qapi-doc::指令机械地注入。同样的模式还用于docs/interop/qemu-ga-ref.rstQGA 协议参考指向qga/qapi-schema.jsondocs/interop/qemu-storage-daemon-qmp-ref.rstQEMU Storage Daemon 的 QMP 参考。也就是说阅读这份手册的正确姿势是把它当作索引把 QAPI 模式当作正文。它回答的是一类问题“QEMU 到底支持哪些 QMP 命令每条命令的参数、返回值、事件的结构是什么”1.1 为什么用“生成”而不是“手写”QMPQEMU Machine Protocol是 QEMU 面向程序员的 JSON 控制协议命令数量庞大且随版本持续增长。如果手写文档几乎必然与实现脱节。QEMU 的解法是让QAPIQEMU API模式成为单一事实源single source of truth开发者在qapi/*.json中用 Python 风格的 DSL 声明命令、事件、结构体、枚举scripts/qapi-gen.py位于 scripts/qapi据此生成 C 代码命令分发、参数解析、序列化以及文档Sphinx 扩展 docs/sphinx/qapidoc.py 解析同一份模式文件把注释渲染成参考手册。因此文档中的每一条命令都与线上行为同源同构不会出现“文档写的是 A实现是 B”的漂移。这一点在 docs/sphinx/qapidoc.py 的模块注释中有明确说明该扩展的用途就是“读取 QAPI schema 文件中的文档注释并将它们全部插入当前文档”。二、生成机制qapidoc 扩展与 qmp-example 指令2.1 qapi-doc 指令docs/sphinx/qapidoc.py 是qemu-qmp-ref.rst能够成文的核心。它注册了两个自定义指令qapi-doc::接收一个参数schema 文件路径相对于源码树根目录例如qapi/qapi-schema.json。执行时它会用qapi.parser.QAPIDoc解析整个 schema并将解析得到的文档节点注入当前 rST 文档见 docs/sphinx/qapidoc.py。它还通过 visitor 机制把所有被 include 的子 schema 文件登记为 Sphinx 的依赖schema 一变手册就会自动重建。qmp-example::一个“QMP 代码示例”告示块。默认情况下其内容按 QMP 词法高亮展示带:annotated:选项时允许在示例中穿插普通 rST 段落实现“讲解 示例”混排见 docs/sphinx/qapidoc.py。2.2 依赖的配置项该扩展要求 docs/conf.py 中设置qapidoc_srctree配置项指向 QEMU 源码树根目录否则无法解析相对路径。整个 QEMU 手册含本参考手册的 HTML 与 man page 都由 docs/meson.build 驱动 Sphinx 构建。2.3 参考手册同时产出 man page在 docs/meson.build 的man_pages映射中可以看到man_pages { ... qemu-qmp-ref.7: man7, ... }而 docs/conf.py 也把interop/qemu-qmp-ref注册为标题为 QEMU QMP Reference Manual 的 man page。也就是说编译安装 QEMU 文档后你可以直接通过man qemu-qmp-ref在本地翻阅这份参考手册。2.4 如何构建这份文档QEMU 使用 Meson Sphinx 构建文档。常规流程是# 1. 配置构建启用文档需要 sphinx-build 与 readthedocs 主题 ./configure --enable-docs # 2. 构建 HTML 手册 ninja -C build qemu-doc-html # 3. 构建 man page含 qemu-qmp-ref.7 ninja -C build qemu-doc # 4. 直接查看 QMP 参考手册的 man page man build/man7/qemu-qmp-ref.7构建要求安装 Python 3 版本的 python-sphinx 与 readthedoc 主题若缺少这些依赖--enable-docs会直接报错见 docs/meson.build。三、内容的源头qapi/qapi-schema.json 与它的 78 个子模式qemu-qmp-ref.rst指向的 qapi/qapi-schema.json 是 QMP 线上 ABI 的总入口。它本身几乎不定义任何类型而是通过{ include: xxx.json }指令把全部子模式按固定顺序串联起来qapi/qapi-schema.json{ include: pragma.json } { include: error.json } { include: common.json } { include: sockets.json } { include: run-state.json } { include: crypto.json } { include: job.json } { include: accelerator.json } { include: block.json } { include: block-export.json } { include: char.json } { include: dump.json } { include: net.json } { include: ebpf.json } { include: rocker.json } { include: tpm.json } { include: ui.json } { include: authz.json } { include: migration.json } { include: transaction.json } { include: trace.json } { include: compat.json } { include: control.json } { include: introspect.json } { include: qom.json } { include: qdev.json } { include: machine-common.json } { include: machine.json } { include: machine-s390x.json } { include: replay.json } { include: yank.json } { include: misc.json } { include: misc-arm.json } { include: misc-i386.json } { include: audio.json } { include: acpi.json } { include: acpi-hest.json } { include: pci.json } { include: stats.json } { include: virtio.json } { include: vfio.json } { include: cryptodev.json } { include: cxl.json } { include: uefi.json }文件注释中特别强调了一个排序约定qapi/qapi-schema.jsonqapi-gen.py 生成的文档按源码顺序排列include 的子模式会插入到第一条 include 指令处后续 include 无效因此每个子模式只 include 一次且尽量在开头集中 include以保证文档顺序稳定。按照功能划分这些子模式覆盖了 QMP 的各个领域你在参考手册中看到的每个章节基本与之一一对应子模式文件覆盖内容qapi/control.jsonQMP 会话控制qmp_capabilities、query-version、query-commands、quitqapi/introspect.jsonquery-qmp-schema内省命令与SchemaInfo类型族qapi/run-state.json运行状态、system_powerdown、quit等生命周期命令qapi/block.json块设备管理驱动、镜像、快照qapi/migration.json迁移相关命令与事件qapi/net.json网络设备与网卡热插拔qapi/machine.json机器类型与query-machines等qapi/qom.jsonQOM 对象内省与管理qapi/transaction.json事务性批量命令transaction...其余见 qapi 目录四、用参考手册的方式从“翻阅手册”到“上手调用”qemu-qmp-ref.rst是手册正文的入口但手册本身假设读者已经了解 QMP 的线级协议格式——命令如何组帧、响应与事件如何表示。这部分由另一份文档 docs/interop/qmp-spec.rstQEMU Machine Protocol Specification规定其中明确写道“协议的一般格式见 qmp-spec命令和数据结构的细节见 qemu-qmp-ref”docs/interop/qmp-spec.rst。两份文档配套阅读spec 讲“语法”ref 讲“词汇表”。4.1 手册中示例的记号约定参考手册的引言即 qapi/qapi-schema.json 中的 Introduction 注释定义了示例记号- ... 客户端发出的文本命令 - ... 服务器发出的文本命令响应与事件并提醒示例文本为了可读性做了格式化真实协议交互中通常是一行发出此外协议本身对 json-object 成员的顺序不做任何保证。4.2 一个完整的 QMP 会话对应手册中的 control 章节以手册中最基础的 qapi/control.json 为例QMP 会话的生命周期非常清晰第 1 步连接并读取 greeting。QMP 服务器如-qmp tcp:localhost:4444,serveron,waitoff在客户端连接后会首先发送一条问候消息。第 2 步能力协商。在发送任何其他命令之前客户端必须先调用qmp_capabilities否则后续命令不会被接受qapi/control.json- { execute: qmp_capabilities, arguments: { enable: [ oob ] } } - { return: {} }要点来自 qapi/control.json 的 note该命令仅在刚连接时有效它必须先于任何其他命令发出一旦 monitor 开始接受其他命令再调用就会失败客户端必须显式启用 QMP capability否则所有 capability 默认关闭目前唯一的 capability 是oobout-of-band带外请求见 qapi/control.json。第 3 步查询与操作。例如查询版本qapi/control.json- { execute: query-version } - { return:{ qemu:{ major:0, minor:11, micro:5 }, package: } }VersionInfo结构qapi/control.json约定micro 为 50 表示开发分支≥90 表示下一个 minor 版本的 RC50 表示稳定版package字段官方构建恒为空字符串下游发行版应填入唯一的非空标识。又如列出当前服务器支持的全部命令qapi/control.json- { execute: query-commands } - { return:[ { name:query-balloon }, { name:system_powerdown }, ... ] }再如优雅退出qapi/control.json- { execute: quit } - { return: {} }注意手册中的提醒quit会尽力在退出前发送响应但不保证因此使用它时客户端应容忍提前 EOF。4.3 运行时内省query-qmp-schema除了翻阅手册QMP 客户端还可以在运行时直接询问 schema。query-qmp-schemaqapi/introspect.json返回一个SchemaInfo数组描述当前 QEMU 二进制支持的每个命令、事件、类型及其参数/返回值。这相当于“把参考手册变成可编程查询的数据”。需要注意手册给出的边界qapi/introspect.jsonSchemaInfo只能表达“接口内省”无法覆盖 QMP 的所有规则与限制权威规范仍是 QAPI schema 本身虽然 QMP 线上格式跨版本尽量保持向后兼容但内省输出的稳定性不保证成员可能从可选变体变成变体、类型可能从字符串泛化为枚举等内省只反映线上 ABIQAPI 也用于定义内部接口这些类型不会出现在返回结果中。SchemaInfo是带判别器的联合体meta-type取值包括builtin、enum、array、object、alternate、command、eventqapi/introspect.json每种 meta-type 再附带各自的附加成员例如command有arg-type与ret-type指向参数/返回值的对象类型名并可带allow-oob标记qapi/introspect.json。一个典型的自动化客户端工作流就是启动 QEMU → 读取 greeting →qmp_capabilities→query-qmp-schema→ 依据返回的 SchemaInfo 生成调用代码。五、如何“读”一份子模式的权威定义由于参考手册正文就是 schema 注释的渲染学会读 schema 就等于学会读手册。以 qapi/control.json 为例一个命令的权威定义通常包含命令名、参数data、返回值returns、Since 版本、示例qmp-example和特性注释。命令定义示例qapi/control.json{ command: qmp_capabilities, data: { *enable: [ QMPCapability ] }, allow-preconfig: true }参数名带*前缀表示可选字段如*enableallow-preconfig: true表示该命令在 preconfig 阶段也可调用data缺省表示无参数如quit。结构体定义示例qapi/control.json{ struct: VersionInfo, data: {qemu: VersionTriple, package: str} }枚举定义示例qapi/control.json{ enum: QMPCapability, data: [ oob ] }这些语法细节的完整规范在 docs/devel/qapi-code-gen.rstQAPI 代码生成文档中参考手册的 introspection 章节也会在描述 alternate 时引用它见 qapi/introspect.json。六、把 QMP 打开命令行入口与配套文档6.1 用 -qmp / -qmp-pretty 开启 QMP参考手册的配套信息位于 qemu-options.hx-qmp dev 像 -monitor 但以 control 模式打开 -qmp-pretty dev 同 -qmp但使用美化后的 JSON 格式输出官方示例在 localhost:4444 暴露 QMPqemu-system-x86_64 ... \ -qmp tcp:localhost:4444,serveron,waitoff-qmp dev本质是“创建字符设备 dev 配对-object monitor-qmp”的语法糖字符设备与 monitor 对象都会获得compat_monitorNNNNNN 从 0 递增这样的自动 ID。从 QEMU 5.0 起monitor 模式本身也是可编程的MonitorMode枚举定义了readlineHMP人类可读命令行与controlQMP两种模式MonitorOptions允许通过-monitor/-object monitor-qmp显式指定 id、mode、pretty 与 chardev见 qapi/control.json。默认模式是系统模拟器中为 readlineqemu-storage-daemon 中为 control。6.2 配套文档地图在 docs/interop/index.rst 中qemu-qmp-ref与以下文档并列共同构成互操作协议文档集文档用途docs/interop/qmp-spec.rstQMP 线级协议规范帧格式、命令/响应/事件语义、OOBdocs/interop/qemu-qmp-ref.rstQMP 命令/事件/类型全量参考本文主角docs/interop/qemu-ga-ref.rstQEMU Guest Agent 协议参考QGA宿主与客户机 OS 交互docs/interop/qemu-storage-daemon-qmp-ref.rstqemu-storage-daemon 的 QMP 参考仅含其支持的子集docs/devel/qapi-code-gen.rstQAPI 模式语言与代码生成规范其余文档也会反向链接回本手册例如 docs/interop/bitmaps.rst 在讲解 dirty bitmap 管理时逐条链接到qemu-qmp-ref.html中的query-block、BlockDirtyInfo、block-dirty-bitmap-add/remove/clear/enable/disable/merge、blockdev-backup等条目——这正体现了参考手册作为全仓库“QMP 词汇表”的枢纽地位。6.3 QGA 与 Storage Daemon同源不同集理解参考手册还有一个重要维度QMP 的“方言”。QEMU 主程序、QEMU Guest Agentqga 目录与 qemu-storage-daemon 各有自己的 QAPI 根 schema因此各自的参考手册覆盖范围不同主 QEMU以 qapi/qapi-schema.json 为根覆盖全部约 46 个子模式文件见 qapi 目录QGAqga/qapi-schema.json 为根聚焦客户机内执行的 guest 命令如guest-info、guest-execStorage Daemon仅暴露存储相关子集反映在 qemu-storage-daemon-qmp-ref.rst 中。查阅时先确认你操作的是哪个“服务器”再翻对应手册避免把 QGA 命令误当成主 QEMU 命令。七、给开发者与自动化运维的实践建议把query-qmp-schema当运行时文档参考手册是离线阅读与协议设计的首选但对于动态环境多版本混部、容器化 QEMU在运行时调用内省命令生成客户端可以避免硬编码命令签名。优先读 schema 注释而非猜测行为每个命令的Since版本、可选参数、默认行为、示例都在 qapi 目录的对应文件中改动 QEMU 版本后第一件事就是 diff 两份 schema。用qmp-example块快速验证语义手册中每个主要命令都附有-/-示例可直接作为socat/nc手工调试 QMP 的最小用例。留意能力协商所有自动化客户端的第一步都必须是qmp_capabilities否则命令会被拒绝需要使用 OOB带外请求时必须在握手时显式启用oobcapability。结合监控层阅读HMPreadline 模式与 QMPcontrol 模式共享大量底层逻辑理解MonitorMode与MonitorOptionsqapi/control.json有助于判断“某条命令能否在 HMP 里找到等价形式”。结语qemu-qmp-ref.rst以 10 行占位符撬动了一份覆盖数千条命令、事件与类型定义的完整机器接口参考。它证明了“单一事实源 文档生成”在大型系统软件中的威力模式即规范、注释即文档、实现与文档永不脱节。对任何想要以编程方式管理 QEMU 的工程师来说这份手册及其背后的 qapi 目录就是最权威、最不会说谎的接口字典——离线读它在线问它动手前先翻它。【免费下载链接】qemuOfficial QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.项目地址: https://gitcode.com/gh_mirrors/qe/qemu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考