当前位置: 首页 > news >正文

libvirt/qemu内存快照的实现原理分析记录

libvirt 内存快照实现原理深度分析1. 概述当你执行virsh snapshot-create-as domain --memspec savefile或virsh snapshot-create domain snapshot.xml其中 XML 指定了memory snapshotexternal/libvirt 会创建一个包含虚拟机内存状态的快照。这看似简单的一条命令背后却涉及 libvirt 多层架构的精密协作——从公共 API 到 QEMU 驱动再到 QEMU Monitor 命令。本文将逐层拆解。2. 快照类型与内存快照定位libvirt 定义了三种内存快照位置snapshot_conf.htypedefenum{VIR_DOMAIN_SNAPSHOT_NOSTATEVIR_DOMAIN_NOSTATE,VIR_DOMAIN_SNAPSHOT_RUNNINGVIR_DOMAIN_RUNNING,VIR_DOMAIN_SNAPSHOT_PAUSEDVIR_DOMAIN_PAUSED,VIR_DOMAIN_SNAPSHOT_SHUTOFFVIR_DOMAIN_SHUTOFF,// ...VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT,// 磁盘快照专用状态}virDomainSnapshotState;快照定义的核心数据结构snapshot_conf.hstruct_virDomainSnapshotDef{virDomainMomentDef parent;intstate;// 快照时的域状态virDomainSnapshotLocation memory;// 内存快照类型internal/external/nochar*memorysnapshotfile;// 外部内存状态文件路径size_tndisks;virDomainSnapshotDiskDef*disks;// ...};关键字段解读memory决定内存快照是internal嵌入 qcow2 磁盘文件、external独立文件还是no不保存内存memorysnapshotfile当 memory 为 external 时保存内存状态的文件路径state快照时刻 VM 的状态回滚时用于判断是否需要恢复内存--memspec本质就是设置memory VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL并指定memorysnapshotfile。3. API 入口与调用链整体调用链如下virDomainSnapshotCreateXML() // 公共 API: src/libvirt-domain-snapshot.c └→ qemuDomainSnapshotCreateXML() // QEMU 驱动实现: src/qemu/qemu_driver.c └→ qemuSnapshotCreateXML() // 快照核心逻辑: src/qemu/qemu_snapshot.c4. 准备阶段qemuSnapshotPrepare在真正执行快照前qemuSnapshotPrepare()qemu_snapshot.c负责校验合法性。关键逻辑staticintqemuSnapshotPrepare(virDomainObj*vm,virDomainSnapshotDef*def,bool*has_manual,unsignedint*flags){bool activevirDomainObjIsActive(vm);// ...for(i0;idef-ndisks;i){switch(disk-snapshot){caseVIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL:found_internaltrue;// 活跃域不能使用内部磁盘快照 外部内存快照的组合break;caseVIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL:external;break;// ...}}// 关键约束内部内存快照要求所有磁盘都参与内部快照if((def-memoryVIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL!found_internal)||(found_internalforbid_internal)){// 报错内部快照要求所有磁盘都参与}// 不允许混合内部和外部if((def-memoryVIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNALfound_internal)){// 报错混合内部和外部目标不支持}}核心约束外部内存快照--memspec 外部磁盘快照✅ 合法组合外部内存快照 内部磁盘快照❌ 不允许内部内存快照 外部磁盘快照❌ 不允许内部内存快照要求所有磁盘都参与内部快照5. 核心执行qemuSnapshotCreateActiveExternal这是内存快照的真正核心入口qemu_snapshot.cstaticintqemuSnapshotCreateActiveExternal(virQEMUDriver*driver,virDomainObj*vm,virDomainMomentObj*snap,virQEMUDriverConfig*cfg,bool has_manual,unsignedintflags){bool memorysnapdef-memoryVIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;bool thawfalse;bool resumefalse;// ...整个流程可以分解为以下阶段5.1 文件系统冻结Quiesceif(flagsVIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE){frozenqemuSnapshotFSFreeze(vm,NULL,0);if(frozen0)thawtrue;// 标记后续需要解冻}如果用户指定了--quiescelibvirt 通过 QEMU Guest Agent 调用fsfreeze冻结客户机文件系统确保磁盘数据一致性。5.2 暂停虚拟机if(virDomainObjGetState(vm,NULL)VIR_DOMAIN_RUNNING){if(memory!has_manual)resumetrue;// 标记后续需要恢复运行if(((memory||has_manual)!(flagsVIR_DOMAIN_SNAPSHOT_CREATE_LIVE))){if(qemuProcessStopCPUs(driver,vm,VIR_DOMAIN_PAUSED_SNAPSHOT,VIR_ASYNC_JOB_SNAPSHOT)0)gotocleanup;}}关键点内存快照必须暂停 VM非 Live 模式下因为需要获取一个一致的内存状态resume标记记录了 VM 原本是运行状态快照完成后需要恢复VIR_DOMAIN_SNAPSHOT_CREATE_LIVE标志允许不暂停 VM但这是渐进式更复杂5.3 创建外部磁盘快照if(qemuSnapshotCreateActiveExternalDisks(vm,snap,blockNamedNodeData,flags,asyncJob)0)gotocleanup;外部磁盘快照通过 QMPtransaction命令原子性地完成为每个磁盘创建 qcow2 overlay 文件使用blockdev-snapshot-sync或blockdev-snapshot命令原始磁盘变为只读 backing file新 overlay 成为活跃层5.4 保存内存状态这是内存快照最关键的步骤if(memory){// 将 VM 状态保存到 memorysnapshotfile 指定的文件if(qemuSaveImageCreate(driver,vm,snapdef-memorysnapshotfile,compressor,asyncJob)0)gotocleanup;memory_unlinktrue;}qemuSaveImageCreate内部调用 QEMU Monitor 的migrate命令将内存页转储到文件QMP: {execute: migrate, arguments: {uri: exec:cat /path/to/savefile}}本质上这个过程和virsh save一样——QEMU 的 live migration 机制被复用来将内存页写入文件。保存的数据包含libvirt save header包含 XML 域定义、cookie 等QEMU vmstate设备状态内存页数据客户机物理内存的完整转储5.5 恢复虚拟机运行cleanup:if(thaw)qemuSnapshotFSThaw(vm,false);// 解冻文件系统if(resumevirDomainObjIsActive(vm))qemuProcessStartCPUs(driver,vm,VIR_DOMAIN_RUNNING_UNPAUSED,VIR_ASYNC_JOB_SNAPSHOT);// 恢复 CPU 运行5.6 错误回滚if(ret0memory_unlink!memory_existing)unlink(snapdef-memorysnapshotfile);// 删除未完成的内存转储文件如果过程中任何步骤失败已创建的内存文件和磁盘 overlay 都会被回滚清理。6. 内部内存快照路径对于内部内存快照memory VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL走的是完全不同的路径qemu_snapshot.cstaticintqemuSnapshotCreateActiveInternal(virQEMUDriver*driver,virDomainObj*vm,virDomainMomentObj*snap,unsignedintflags){// 1. 暂停 VMif(virDomainObjGetState(vm,NULL)VIR_DOMAIN_RUNNING){qemuProcessStopCPUs(driver,vm,VIR_DOMAIN_PAUSED_SAVE,...);resumetrue;}// 2. 通过 QMP 发送 snapshot-save 命令jobqemuSnapshotCreateActiveInternalStart(vm,snapdef);// 内部调用: qemuMonitorSnapshotSave()// 3. 等待异步 job 完成while((rvqemuSnapshotCreateActiveInternalDone(vm,job))!1){qemuDomainObjWait(vm);}}内部快照使用 QMP 命令snapshot-savercqemuMonitorSnapshotSave(qemuDomainGetMonitor(vm),jobname,snapdef-parent.name,devices[0],(constchar**)devices);这个命令将 vmstate内存 设备状态嵌入到 qcow2 磁盘映像文件中。QEMU 的 qcow2 格式本身支持这种 vmstate 存储机制。外部 vs 内部内存快照对比维度外部--memspec内部内存存储位置独立文件qcow2 磁盘文件内部磁盘快照类型必须 external必须 internalQEMU 命令migrate到文件snapshot-save磁盘格式要求无特殊必须 qcow2文件系统影响额外产生一个文件qcow2 文件膨胀7. 回滚Revert到内存快照当执行virsh snapshot-revert回滚到内存快照时流程如下在qemuSnapshotRevertActive中如果目标快照包含内存状态memory ! NO且state PAUSED/RUNNING如果 VM 正在运行先停止 VM使用qemuProcessStart()重新启动 VM并传入内存快照文件qemuProcessStart内部通过 QEMU 的-incoming参数和migrate incoming恢复内存状态如果快照状态是PAUSED恢复后保持暂停如果目标快照没有内存状态state SHUTOFF停止 VM切换磁盘到快照对应的状态VM 保持关闭8. QEMU 层面内存保存的底层机制当 libvirt 调用qemuSaveImageCreate时最终的 QEMU 执行路径libvirt: qemuSaveImageCreate() └→ qemuMonitorMigrateToFile() └→ QMP: {execute: migrate, arguments: {uri: exec:...}} └→ QEMU: migration/thread → RAM save → vmstate_save → 写入文件QEMU 的 migration 框架被复用于内存转储RAM save遍历客户机物理内存页逐页写入目标通常经过压缩vmstate save保存所有虚拟设备的状态CPU 寄存器、设备配置等数据流经过 libvirt 的 compressor 管道可选压缩最终写入memorysnapshotfile9. 完整流程图virsh snapshot-create-as --memspec savefile │ ▼ virDomainSnapshotCreateXML() ← 公共 API │ ▼ qemuDomainSnapshotCreateXML() ← QEMU 驱动 │ ▼ qemuSnapshotCreateXML() ← 解析 XML、创建 snapdef │ ▼ qemuSnapshotPrepare() ← 校验磁盘/内存快照组合合法性 │ ▼ qemuSnapshotCreateActiveExternal() │ ├── 1. FSFreeze (quiesce) ← QEMU Guest Agent ├── 2. StopCPUs ← 暂停 VM ├── 3. External Disk Snapshot ← QMP transaction (blockdev-snapshot) ├── 4. Save Memory State ← QMP migrate → memorysnapshotfile ├── 5. FSThaw ← 解冻文件系统 └── 6. StartCPUs ← 恢复 VM 运行10. 总结libvirt 的内存快照实现是一个精密的多层协作过程配置层snapshot_conf定义快照元数据区分memory字段的 internal/external/no校验层qemuSnapshotPrepare确保磁盘和内存快照类型的兼容性执行层qemuSnapshotCreateActiveExternal编排暂停、磁盘快照、内存转储、恢复的完整序列QEMU 层通过 QMPtransaction完成磁盘快照通过migrate完成内存转储外部内存快照--memspec的设计哲学是解耦——内存状态和磁盘状态分别存储在独立文件中不依赖 qcow2 的内部快照能力这为存储后端的灵活性提供了基础。
http://www.zskr.cn/news/1382998.html

相关文章:

  • 我仓库内cad python 有哪些应用到聚类的方法
  • taotoken token plan套餐在实际开发中的成本节省感受
  • 拒绝API依赖!为什么“看懂屏幕”才是AI数字员工的终极形态?
  • SQLMap入门笔记:从漏洞原理到自动化数据提取的保姆级教程
  • 一份来自 Karpathy 的 AI 编程 skill
  • Pytest运行方式扫盲:从‘右键运行’到‘命令行高手’的避坑指南(附常见报错解决)
  • 从零开始:Icarus Verilog 开源硬件仿真器完全指南 [特殊字符]
  • 短视频矩阵系统的技术演进:当AI Agent重新定义全域内容运营
  • BiliBiliCCSubtitle深度解析:高效自动化B站字幕下载与转换的专业解决方案
  • 团队协作中如何使用 Taotoken CLI 工具一键统一所有成员的开发环境配置
  • 一些SVG小图标去哪里找
  • 投资者网:2026年GEO服务商五强:领航者的制胜逻辑与实战分析 - 罗兰艺境GEO
  • DyberPet桌面宠物框架:打造属于你的数字伙伴,让桌面互动更有温度
  • 气体涡轮流量计厂家排行榜 - 仪表品牌榜
  • 告别鼠标点击,微博图片批量下载的轻松方案
  • 如何快速将B站缓存视频转为MP4:3步实现永久保存的终极免费工具
  • 泰拉瑞亚地图编辑器终极指南:如何用免费开源工具重塑你的游戏世界
  • Windows服务器风扇狂转的挖矿病毒排查指南
  • 户外热潮来袭——AI赋能冲锋衣设计新潮流
  • 终极解决方案:5步实现WeMod完整功能解锁与远程控制
  • WSL2图形化不止一种玩法:除了VcXsrv,试试这些更轻量的远程桌面方案(含RDP/Wayland)
  • 突破性架构革命:RPFM如何用Rust+Qt6重塑Total War模组开发范式
  • 3种高效玩法:用DRG存档编辑器重塑你的《深岩银河》冒险体验
  • 批量安装Windows系统(WDS + DHCP 独立模式)
  • 靠谱的1688陪跑公司怎么找?立誉企业管理咨询值得信赖 - 品牌企业推荐师(官方)
  • Icarus Verilog:为什么这个开源仿真器成为数字电路验证的首选?
  • 研途灵伴——联调我修了七个 Bug
  • DeepSeek性能基线测试不达标?2024最新《LLM服务端压测白皮书》仅开放72小时下载(含CUDA 12.4适配校验表)
  • GitMemo 安卓版发布了:现在可以随时随地查看和记录自己的笔记
  • 好用还专业!2026年最流行AI论文软件榜单,高质初稿轻松写