news 2026/5/25 7:55:05

深入 QEMU 热迁移

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入 QEMU 热迁移

深入 QEMU 热迁移:从状态机到数据平面的全链路剖析

“把一台正在运行的虚拟机从一台主机搬到另一台,还让里面的操作系统浑然不觉——这听起来像魔法,实则是精密的工程。”

引言

实时迁移是 QEMU 最核心的子系统之一。它允许将一个正在运行的虚拟机透明地从源主机迁移到目的主机,停机时间通常控制在几百毫秒以内。整个迁移框架在客户机继续执行的同时,传输完整的 VM 状态——RAM、设备寄存器、CPU 状态等——宛如在飞驰的列车上更换引擎。

本文基于 QEMU 源码中 migration/ 目录的约 30 个源文件,从架构、状态机、数据平面、压缩与加速四个维度,对热迁移系统进行全链路剖析。


一、架构概览:源端与目的端的职责分离

QEMU 的迁移子系统围绕源端(出站迁移)和目的端(入站迁移)之间清晰的职责分离来构建,两者通过一种与传输方式无关的字节流进行连接。

┌─────────────────── Source Host ───────────────────┐ ┌─────────────────── Destination Host ──────────────┐ │ │ │ │ │ ┌──────────────────┐ │ │ ┌──────────────────┐ │ │ │ MigrationState │ ┌─────────┐ QEMUFile │ │ QEMUFile ┌─────────┐ │ MigrationIncoming│ │ │ │ (migration.c/h) │──│ QIOCh. │════════════════│─────│════════════════│ QIOCh. │──│ State │ │ │ │ │ └─────────┘ │ │ └─────────┘ │ (migration.c/h) │ │ │ │ - to_dst_file │ │ │ │ - from_src_file │ │ │ │ - rp_state │ ←── Return Path ──────────│─────│────────── Return Path ────→ │ - to_src_file │ │ │ └──────────────────┘ │ │ │ - fault_thread │ │ │ │ │ └──────────────────┘ │ └────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────┘

关键数据结构:

  • MigrationState:源端核心状态机,持有to_dst_file(到目的端的文件流)、返回路径线程状态、迁移参数、能力位图、COLO 状态等。
  • MigrationIncomingState:目的端核心状态,持有from_src_file、userfault fd、page request 树、后拷贝信号量等。

两者之间的通信通过QEMUFile抽象进行,底层由QIOChannel提供传输无关的字节流,支持 TCP socket、UNIX socket、exec、RDMA 等多种后端。


二、迁移状态机:精密编排的状态流转

每个迁移实例都经历一系列定义明确的状态推进,通过 QMP 暴露的MigrationStatus枚举进行跟踪。理解这个状态机是理解整个迁移流程的钥匙。

┌──────────┐ │ none │ └────┬─────┘ │ migrate QMP command ┌────▼─────┐ │ setup │ ←── 初始化通道、multifd 线程 └────┬─────┘ │ ┌────▼─────┐ ┌─────│ active │──────┐ │ └────┬─────┘ │ │ │ │ converging postcopy pause-before │ trigger switchover │ │ │ ┌─────▼──┐ ┌────▼──────┐ ┌───▼───────────┐ │wait- │ │postcopy- │ │pause-before- │ │device │ │active │ │switchover │ └───┬────┘ └────┬──────┘ └───┬───────────┘ │ │ │ ▼ ▼ ▼ ┌───────────────────────────────┐ │ completed │ └───────────────────────────────┘ 任何状态 ──→ failing ──→ failed postcopy-active ──→ postcopy-pause ──→ postcopy-recover

状态转换的核心逻辑在 migration.c 中定义,migrate_set_state()负责原子地更新状态并触发 QMP 事件通知。


三、预拷贝迁移生命周期

默认的迁移模式是预拷贝(precopy),即在客户机继续运行的同时传输大部分内存。

3.1 主循环:迭代传输脏页

源端迁移线程的入口是 migration_thread(),其核心循环如下:

// 简化后的主循环逻辑while(migration_is_active()){if(urgent||!migration_rate_exceeded(s->to_dst_file)){MigIterateState iter_state=migration_iteration_run(s);// 迭代传输脏页...}thr_error=migration_detect_error(s);// 检测网络故障等urgent=migration_rate_limit();// 速率限制与紧迫页处理}

每一轮迭代:

  1. 扫描脏位图,找出自上次传输以来被修改的内存页
  2. 传输脏页到目的端
  3. 检查收敛条件:剩余脏页是否低于threshold_size(由期望停机时间和实测带宽计算得出)
  4. 若收敛,进入 switchover 阶段;否则继续迭代

3.2 脏页追踪

脏页追踪是预拷贝迁移的基石。QEMU 通过DirtyMemoryBlocksRCU 方案实现高效的脏位图扫描:

  • 迁移线程持有 RCU 读锁(而非更重的 ramlist 互斥锁)扫描位图
  • RAM 热插拔操作可以并发扩展位图
  • 每个 RAMBlock 嵌入了bmapreceivedmapclear_bmapfile_bmap等迁移专用位图

3.3 CPU 节流:自动收敛

当脏页产生速度超过传输速度时,QEMU 会启动自动收敛机制——通过 cpu-throttle.c 降低 vCPU 执行频率,迫使客户机产生脏页的速度下降,直至迁移收敛。最大节流比例由max-cpu-throttle参数控制(默认 99%)。


四、后拷贝迁移:用缺页中断换停机时间

后拷贝是一种激进的迁移策略:先快速传输 CPU 状态和非 RAM 设备状态,让 VM 在目的端尽早启动,然后按需拉取内存页。

4.1 核心机制:userfaultfd

后拷贝的核心依赖是 Linux 的userfaultfd系统调用。目的端 QEMU 在迁移开始前:

  1. 为所有 RAMBlock 注册 userfaultfd 区域
  2. 启动 fault_thread 监听缺页事件
  3. 当 VM 在目的端访问尚未传输的页面时,内核暂停该 vCPU 并通知 fault_thread
  4. fault_thread 通过返回路径向源端发送MIG_RP_MSG_REQ_PAGES请求
  5. 源端的 source_return_path_thread() 收到请求后,优先传输被请求的页面
// 目的端请求页面的核心逻辑(简化)intmigrate_send_rp_req_pages(MigrationIncomingState*mis,RAMBlock*rb,ram_addr_tstart,...){WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex){if(!ramblock_recv_bitmap_test_byte_offset(rb,start)){g_tree_insert(mis->page_requested,aligned,(gpointer)1);qatomic_inc(&mis->page_requested_count);}}// 向源端发送 REQ_PAGES 消息...}

4.2 后拷贝抢占

后拷贝面临一个经典问题:当源端正在传输后台批量页面时,目的端突然发生紧急缺页,请求的页面可能被排在长队列后面。

解决方案是后拷贝抢占——建立一条独立的紧急通道(postcopy_qemufile_dst),由专门的 postcopy_prio_thread 处理。紧急页面通过这条通道优先传输,避免被批量数据阻塞。

4.3 页面请求的空间局部性优化

QEMU 还利用了空间局部性原理,通过 PageLocationHint 结构,在后拷贝抢占模式下,源端在发送紧急请求页之后,会顺便发送相邻的页面,减少未来的缺页中断次数。


五、Multifd:并行传输引擎

单通道传输在高带宽网络上是瓶颈。Multifd 通过创建 N 条并行通道来充分利用带宽。

5.1 架构

定义在 multifd.h,multifd 在源端创建 N 个发送线程(mig/src/send_%d),在目的端创建 N 个接收线程(mig/dst/recv_%d),通道数由x-multifd-channels参数控制(默认 2)。

Source Destination ┌──────────────┐ ┌──────────────┐ │ Main Thread │═══════════════════│ Main Thread │ ├──────────────┤ ├──────────────┤ │ send_0 │═══════════════════│ recv_0 │ │ send_1 │═══════════════════│ recv_1 │ │ ... │ │ ... │ │ send_N-1 │═══════════════════│ recv_N-1 │ └──────────────┘ └──────────────┘

每个 multifd 包的结构定义在 MultiFDPacket_t:

typedefstruct{MultiFDPacketHdr_t hdr;// magic + version + flagsuint32_tpages_alloc;// 最大分配页数uint32_tnormal_pages;// 非零页数uint32_tnext_packet_size;// 数据负载大小uint64_tpacket_num;// 包序号uint32_tzero_pages;// 零页数charramblock[256];// 所属 RAMBlock 名称uint64_toffset[];// 每页的偏移量}MultiFDPacket_t;

5.2 可插拔压缩后端

Multifd 的压缩后端是完全可插拔的,每个后端实现为独立文件:

后端文件说明
无压缩multifd-nocomp.c基线,直接传输原始页
zlibmultifd-zlib.c通用压缩
zstdmultifd-zstd.c高压缩比
Intel QPLmultifd-qpl.cIntel 硬件加速
Huawei UADKmultifd-uadk.c华为硬件加速
Intel QATzipmultifd-qatzip.cIntel QAT 压缩卡

压缩标志通过MULTIFD_FLAG_COMPRESSION_MASK位域标识,接收端根据 flags 分派到对应的解压函数。


六、返回路径:双向通信的生命线

迁移并非单向数据流。目的端需要向源端发送控制消息,例如请求特定页面、确认切换、报告接收位图等。这就是返回路径(Return Path)。

源端的 source_return_path_thread() 专门处理来自目的端的消息,消息类型定义在 mig_rp_message_type:

消息类型方向用途
MIG_RP_MSG_SHUTDST→SRC目的端关闭,不再发送 RP 消息
MIG_RP_MSG_PONGDST→SRC响应 PING,确认通道存活
MIG_RP_MSG_REQ_PAGESDST→SRC后拷贝期间请求特定页面
MIG_RP_MSG_REQ_PAGES_IDDST→SRC带 RAMBlock ID 的页面请求
MIG_RP_MSG_RECV_BITMAPDST→SRC回传接收位图
MIG_RP_MSG_RESUME_ACKDST→SRC确认已准备好恢复
MIG_RP_MSG_SWITCHOVER_ACKDST→SRC确认可以执行切换

返回路径的建立通过 open_return_path_on_source() 完成,它从to_dst_file的底层 QIOChannel 获取反向文件句柄,并启动专门的线程。


七、设备状态序列化:VMState 框架

迁移不仅是搬运内存页——设备的内部状态同样需要完整传输。QEMU 通过VMState框架实现设备状态的声明式序列化。

每个可迁移设备通过SaveVMHandlers注册一组回调:

回调用途
save_setup/load_setup初始化迁移传输
save_live_iterate预拷贝迭代中传输可迭代状态
save_live_complete_precopy预拷贝最终阶段传输剩余数据
has_postcopy指示是否支持后拷贝模式
save_postcopy_prepare为向后拷贝转换做准备
load_state接收并应用状态数据
save_cleanup/load_cleanup迁移完成后释放资源

VirtIO 设备的迁移尤为复杂,通过多子节 VMState 描述处理(virtio.c 附近的vmstate_virtio),仅当设备状态与默认值不同时才序列化,减少传输量。


八、专用传输与高级特性

8.1 RDMA 迁移

rdma.c 实现了基于 RDMA 的迁移通道,利用远程直接内存访问绕过内核协议栈,在高带宽低延迟网络(如 InfiniBand)上大幅提升传输性能。源端通过 RDMA WRITE 操作直接将页面写入目的端内存,无需目的端 CPU 参与。

8.2 COLO:连续带外活体复制

colo.c 实现了 COLO(COntinuous LOck-step)模式——主备 VM 同步运行,通过比较输出实现近乎零停机的容错。当检测到输出不一致时回滚到上一检查点,适合对可用性要求极高的场景。

8.3 CPR:进程检查点与重启

cpr.c 和 cpr-exec.c 实现了 CPR(CheckPoint and Restart)迁移模式,允许将 VM 状态保存后在同一主机的新 QEMU 进程中恢复,用于 QEMU 升级等场景。

8.4 XBZRLE:增量编码缓存

xbzrle.c 实现了基于 XOR 的增量编码。源端维护一个页面缓存,每次传输时只发送当前页与缓存版本的差异,对于频繁修改相同页面的工作负载(如数据库)效果显著。


九、关键配置参数速查

参数默认值说明
downtime-limit300 ms最大允许停机时间
max-bandwidth1 GiB/s迁移最大带宽
x-multifd-channels2并行 multifd 通道数
x-multifd-page-count16每个 multifd 包的页数
x-xbzrle-cache-size64 MiBXBZRLE 增量缓存大小
max-cpu-throttle99%最大 CPU 节流比例

十、源码导航地图

migration/ ├── Core State Machine │ ├── migration.c/h — 状态机、主循环、QMP 命令实现 │ ├── options.c/h — 迁移参数解析与校验 │ └── global_state.c — 全局 VM 状态序列化 ├── Transport Layer │ ├── channel.c/h — QIOChannel 迁移通道抽象 │ ├── socket.c/h — TCP/UNIX socket 传输 │ ├── fd.c/h — 文件描述符传输 │ ├── file.c/h — 文件传输 │ ├── exec.c/h — exec 传输 │ ├── rdma.c/h — RDMA 传输 │ └── tls.c/h — TLS 加密传输 ├── RAM Migration │ ├── ram.c/h — RAM 脏页追踪、迭代传输 │ ├── xbzrle.c/h — XBZRLE 增量编码 │ ├── page_cache.c/h — 页面缓存(XBZRLE 用) │ └── dirtyrate.c/h — 脏页速率统计 ├── Multifd Parallel Engine │ ├── multifd.c/h — 多通道并行框架 │ ├── multifd-nocomp.c — 无压缩基线 │ ├── multifd-zlib.c — zlib 压缩 │ ├── multifd-zstd.c — zstd 压缩 │ ├── multifd-qpl.c — Intel QPL 硬件加速 │ ├── multifd-uadk.c — 华为 UADK 加速 │ ├── multifd-qatzip.c — Intel QAT 压缩卡 │ └── multifd-zero-page.c — 零页优化 ├── Postcopy │ ├── postcopy-ram.c/h — 后拷贝 RAM 处理、userfaultfd ├── COLO │ ├── colo.c — COLO 主逻辑 │ ├── colo-failover.c — COLO 故障切换 │ └── multifd-colo.c/h — COLO multifd 集成 ├── CPR │ ├── cpr.c — CPR 公共逻辑 │ ├── cpr-exec.c — CPR exec 模式 │ └── cpr-transfer.c — CPR transfer 模式 ├── Device State │ ├── savevm.c/h — VMState 保存/恢复入口 │ ├── vmstate.c — VMState 描述符处理 │ ├── vmstate-types.c — 常用类型序列化 │ ├── block-active.c — 块设备活跃状态 │ ├── block-dirty-bitmap.c — 块设备脏位图 │ └── vfio.c / vfio-stub.c — VFIO 设备状态迁移 └── Infrastructure ├── qemu-file.c/h — 迁移字节流抽象 ├── migration-stats.c/h — 迁移统计信息 ├── cpu-throttle.c — CPU 节流 └── yank_functions.c — 网络中断安全清理

结语

QEMU 的热迁移系统是一个精巧的分布式状态机——它要在源端和目的端之间协调数十 GB 的内存传输、数千个设备的状态序列化、亚秒级的停机时间控制,还要优雅地处理网络中断和硬件故障。理解它的关键在于:

  1. 状态机是骨架——所有行为都受MigrationStatus枚举驱动
  2. 脏页追踪是心脏——决定了什么数据需要传输
  3. Multifd 是肌肉——提供并行传输的吞吐量
  4. 后拷贝是利刃——用缺页中断换取极致的停机时间
  5. VMState 是灵魂——确保设备状态完整一致

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 7:54:59

英语 16 大时态 | 一页速记版(核心区别 + 易错点)

一、时态底层逻辑速分法所有时态都由「时间轴(过去 / 现在 / 将来 / 过去将来)」「动作状态(一般 / 进行 / 完成 / 完成进行)」组合而成,掌握这两个维度,就能一眼区分时态本质。二、16 大时态核心区别 易错…

作者头像 李华
网站建设 2026/5/25 7:52:04

神经网络与深度学习(二)

五、深度学习视觉应用1、数据集常用数据集包括MNIST、Fashion-MNIST、CIFAR-10、PASCAL VOC、MS COCO、ImageNet、JFT-300M等。2、任务评价指标(1)精确率P与召回率RPTP/(TPFP) ,表示“挑剔”的程度RTP/(TPFN) &#x…

作者头像 李华
网站建设 2026/5/25 7:52:03

工业异常检测实战:从多模态数据集构建到AI模型评估全解析

1. 项目概述与核心价值在化工、制药、能源等流程工业领域,生产装置的平稳运行是安全与效益的基石。异常检测技术,作为保障这方基石的关键工具,其核心任务是从海量的传感器数据中,敏锐地捕捉到那些预示着潜在故障或性能衰退的“异常…

作者头像 李华
网站建设 2026/5/25 7:50:01

引力波透镜探测:参数偏移与似然比检验的统计框架与应用

1. 引力波透镜探测:从参数估计到一致性检验在引力波天文学领域,确认两个看似独立的引力波事件是否源自同一个天体物理源,只是被前景大质量天体(如星系或星系团)的引力透镜效应放大了,是当前一个极具挑战性且…

作者头像 李华
网站建设 2026/5/25 7:46:08

(毕业必看)实测靠谱的AI写作辅助软件,毕业生收藏备用

毕业季论文写作真的这么难?选题纠结、文献翻不完、初稿写不顺、查重压力山大、格式总不对…… 这份精心整理的AI写作辅助工具清单,覆盖中英文论文需求,从开题到定稿全程可用,功能涵盖写作、降重、格式调整等专项服务,免…

作者头像 李华
网站建设 2026/5/25 7:41:56

YOLO26涨点改进| TIP 2025顶刊| 独家创新首发、特征融合改进篇| 引入DAM解耦注意力融模块,通过强化关键空间特征信息,助力小目标检测、RGB-D目标检测、多模态融合目标检测有效涨点

一、本文介绍 🔥本文给大家介绍使用 DAM解耦注意力融模块 改进YOLO26网络模型,增强模型对复杂场景下目标区域的特征表达与多尺度信息融合能力。DAM 通过水平与垂直方向的解耦注意力机制,在较低计算开销下强化关键空间特征,同时抑制背景噪声,提高模型对小目标、遮挡目标及…

作者头像 李华