资讯动态

smolvm 检查点格式规范全解:文件容器、清单与世系历史的可移植快照格式

发布时间:2026/10/10 9:57:17 来源:尧图企业网站定制
虚拟化AI Agent人工智能CLI【免费下载链接】smolvmAn embeddable, portable, branchable virtual machine to safely run Agents locally.项目地址https://gitcode.com/gh_mirrors/sm/smolvm点击查看免费下载本文档围绕 crates/smolvm-checkpoint/FORMAT.md 展开完整剖析 smolvm 的检查点checkpoint格式一台机器在某一时刻的活体状态如何落盘为单个文件、检查点存储如何以目录形式组织、以及每条检查点如何记录自己的世系lineage。本文面向希望在不阅读 smolvm 源码的前提下读取、校验并产出检查点的第三方程序同时也结合仓库源码说明该格式在 Rust 层的实际实现与使用方式。读完本文你将能理解.checkpoint文件的字节级布局、manifest 中每个字段的含义、内容寻址存储与增量历史的工作原理并能在自己的工具链中正确读写检查点。1. 概述检查点是什么一个检查点是一台机器在暂停瞬间的完整快照guest RAM、vCPU 与设备状态、guest 物理内存布局以及该机器的磁盘全部在同一暂停点采集。每条检查点还记录世系lineage一个唯一 id、它来自的机器名以及它的parent——即该机器上次被捕获为或恢复自的检查点。按 FORMAT.md 的定义检查点有三种形态形态是什么版本Checkpoint file检查点文件一个文件承载一代generation4payload: assetsHistory file历史文件一个文件承载一代及其保留的祖先5payload: chunkedStored checkpoint存储的检查点检查点存储中的一个目录索引、内容寻址对象、保留的祖先index 版本 1内嵌版本 4 的 manifest两种文件共用同一容器第 3 节。历史文件的 payload 就是一个存储检查点目录解包后第 7、8 节同样适用。读者绝不能依据文件扩展名判断文件类型——决定权在 manifest第 5 节。文件扩展名为.checkpoint早期的.smolcheckpoint名称也兼容接受。格式速览检查点版本为4单代与5携带历史存储索引版本为1容器版本为 pack footer 版本1读者可接受1–3。2. 通用约定二进制结构中的整数均为无符号小端序unsigned little-endian。JSON 使用 UTF-8字段名必须与本文列出的一字不差snake_case。哈希为小写十六进制sha256指 SHA-256FIPS 180-4。generation id为 32 个小写十六进制字符128 随机位无内容语义。时间戳为 RFC 3339 UTC、整秒精度例如2026-09-22T10:12:03Z。3. 文件容器检查点文件或历史文件布局如下offset 0 A AM AM64 | payload | manifest | footer | | A bytes | M bytes, JSON | 64 bytes |A来自 footer 的assets_sizeM来自manifest_size。3.1 Footer文件尾 64 字节偏移大小字段检查点中的值08magicASCIISMOLPACK53 4D 4F 4C 50 41 43 4B84version1128stub_size0208assets_offset0288assets_sizeA即 payload 长度368manifest_offsetA448manifest_sizeM即 manifest 长度524checksumCRC-32见 3.2568reserved写入方必须写零读取方必须忽略检查点必须精确满足此布局stub_size 0、assets_offset 0、manifest_offset assets_size且文件长度恰好为A M 64。读者必须拒绝在 manifest 与 footer 之间、或 footer 之后存在多余字节的检查点——这保证除 footer 外的每一个字节都参与校验和。M不得超过 16 MiB。需要说明的是同一容器也承载.smolmachinepack它们可能采用其他布局那些规则不属于本规范范围。容器 magicSMOLPACK的常量定义可见 crates/smolvm-pack/src/format.rspub const MAGIC: [u8; 8] bSMOLPACK;。3.2 校验和checksum是 IEEE 802.3 多项式的 CRC-32与 zlib、crc32fast一致覆盖字节区间[0, A M)即payload 与 manifest。读者必须按以下顺序处理读 footer检查 magic 与版本1、2或3并检查上述边界条件对[0, A M)计算校验和并与 footer 比对只有通过之后才能解析 manifest 或读取 payload。读者应通过同一个打开的文件句柄读取并应在校验期间文件发生变化时拒绝。smolvm 的做法是比较校验前后的 device、inode、长度、修改时间与变更时间。校验和只能检测损坏不提供任何认证——参见第 10 节。3.3 Payloadpayload 是单个 zstd 流包含一个 tar 归档。写入方使用 level 3 压缩读者必须接受任意合法的 zstd 流。读者只应解压文件的前A个字节。tar 条目使用 GNU 格式。guest RAMcheckpoint/memory.bin与 raw 磁盘可以是 GNU sparse 条目类型S其realsize为逻辑长度空洞读作零。写入方按顶层名称排序条目。读者必须解包到全新目录并拒绝任何解析..后越出该目录的路径以及目标越出的符号链接或硬链接读者不得创建设备节点或 FIFO。smolvm 还限制一次解包最多 2,000,000 个条目、128 GiB 声明大小。4. 清单Manifestmanifest 是一个 JSON 对象即 pack manifest。一个文件是检查点当且仅当其 manifest 含有checkpoint对象。读者必须忽略本节约束范围内每个对象中未知的字段。4.1 Pack manifest 字段这些字段描述检查点捕获自的机器。检查点的读者通常只需要platform、secret_refs与checkpoint。字段类型含义modecontainer|vm检查点为vmimagestring检查点为vm://machine namedigeststring检查点为noneplatformstringguest 平台例如linux/arm64其架构必须与恢复主机匹配host_platformstring捕获主机的平台cpus,meminteger配置的 vCPU 数与 MiBentrypoint,cmd,envstring 数组可选workdir,userstring可选secret_refsobject可选。检查点绝不能携带任何 secret refs见第 10 节created,smolvm_versionstring信息性字段assetsobjectpayload 中运行时文件的清单第 6 节checkpointobject检查点 manifest第 4.2 节这些类型在 Rust 侧由smolvm_pack::format::PackManifest定义并经由 crates/smolvm-checkpoint/src/lib.rs 的pub use smolvm_pack::format;重新导出为smolvm_checkpoint::format。4.2checkpoint对象字段类型必填含义versioninteger是payload: assets时为4payload: chunked时为5runtime_abistring是libkrun-portable-snapshot-v1host_platformstring是捕获主机darwin/arm64、linux/amd64、linux/arm64、windows/amd64cpu_contractobject是第 4.4 节cpusinteger是vCPU 数至少 1memory_mibinteger是guest RAMMiB至少 1storage_gibinteger否存储盘大小overlay_gibinteger否overlay 盘大小device_profilestring是有packed_layers时为smolvm-packed-layers-v1否则为smolvm-basic-v1stateasset是vCPU 与设备状态memoryasset是guest RAMlayoutasset是guest 物理内存布局disksarray是第 4.5 节workloadobject否第 4.6 节无镜像的机器缺省networkobject是第 4.7 节packed_layersobject否第 4.8 节lineageobject否第 4.3 节仅在世系机制出现之前写入的检查点缺省payloadassets|chunked否默认assetshistoryarray否仅payload: chunked时出现。第 8.2 节credential_caasset否机器的凭据 CA。第 10 节asset定义为{ path: string, size: integer, sha256: string }path相对 payload 根目录size为未压缩长度sha256为文件字节的哈希。memory与每个磁盘文件的sha256为空字符串其完整性依赖容器校验和或在存储中依赖逐对象哈希。4.3lineage字段类型含义idstringgeneration id32 个十六进制字符parentstring可选。父代的 generation idmachinestring捕获自的机器名created_atstring捕获时间4.4cpu_contract一个带标签的对象kind选择变体。kind其他字段主机何时兼容linux-kvm-intel-portable-v1无它是 IntelGenuineIntelLinux KVM 主机aarch64-features-v1features排序的FEAT_*名称数组它具备列出的每一个特性超集也可以exact-v1fingerprint主机 CPU 身份的 SHA-256 hex其指纹完全一致4.5disks恰有两条链按序先是role: storage再是role: overlay。每条为{ role: string, files: [...] }文件按机器挂载的盘index 0向下排到其 base。每个文件字段类型含义assetasset路径checkpoint/disks/role/indextargetstring文件安装时的名称index 0 为role.raw或role.qcow2其下为.smolcheckpoint-role-index.formatformatraw|qcow2raw文件必须是其链中的最后一个每个 qcow2 文件的 backing file 名称必须是链中下一个文件的target。一条链至多 64 个文件。target中的.smolcheckpoint-前缀是格式的一部分不受文件扩展名影响。4.6workload字段类型含义imagestring镜像引用非空userstring可选overlay_ownerstring拥有 overlay 的机器须为合法机器名restart_policystringnever、always、on-failure或unless-stoppedrestart_max_retriesinteger0 表示不限次数restart_max_backoff_secsinteger0 表示运行时默认值4.7network字段类型含义enabledboolean出站网络backendtsi|virtio-net可选ports{ host, guest }数组可选。非零、唯一的主机端口要求virtio-netallowed_cidrs,dns_filter_hostsstring 数组可选的出站策略guest_subnetstring可选credential_policyobject可选。第 10 节credential_placeholdersobject可选。环境变量名到占位值的映射非机密dns与network_name虽有定义但捕获从不写入它们使用自定义 DNS 或命名网络的机器无法被检查点化。4.8packed_layers当机器从.smolmachinepack 挂载镜像层时出现artifact_sha256hex无前缀、footer_checksum该 pack 的 CRC-32以及可选的registry_ref。pack不在检查点内部恢复主机必须已持有该 pack并按摘要与校验和核验。4.9 完整示例{ mode: vm, image: vm://worker, digest: none, platform: linux/arm64, host_platform: darwin/arm64, cpus: 2, mem: 1024, assets: { ...: runtime inventory, section 6 }, checkpoint: { version: 4, runtime_abi: libkrun-portable-snapshot-v1, host_platform: darwin/arm64, cpu_contract: { kind: aarch64-features-v1, features: [FEAT_AES, FEAT_SHA256] }, cpus: 2, memory_mib: 1024, storage_gib: 20, overlay_gib: 10, device_profile: smolvm-basic-v1, state: { path: checkpoint/checkpoint.bin, size: 123456, sha256: 9b1c… }, memory: { path: checkpoint/memory.bin, size: 1073741824, sha256: }, layout: { path: checkpoint/manifest.bin, size: 512, sha256: 4e07… }, disks: [ { role: storage, files: [ { asset: { path: checkpoint/disks/storage/0, size: 21474836480, sha256: }, target: storage.raw, format: raw } ] }, { role: overlay, files: [ { asset: { path: checkpoint/disks/overlay/0, size: 196608, sha256: }, target: overlay.qcow2, format: qcow2 }, { asset: { path: checkpoint/disks/overlay/1, size: 10737418240, sha256: }, target: .smolcheckpoint-overlay-1.raw, format: raw } ] } ], workload: { image: alpine:3.20, overlay_owner: worker, restart_policy: never, restart_max_retries: 0, restart_max_backoff_secs: 0 }, network: { enabled: true, backend: tsi }, lineage: { id: 9f2c1a7b3e4d5f60718293a4b5c6d7e8, parent: 51e0d8c2a9b4c3d2e1f0a9b8c7d6e5f4, machine: worker, created_at: 2026-09-22T10:12:03Z }, payload: assets } }5. 识别与打开检查点若路径是一个包含checkpoint.json的目录则它是存储检查点第 7 节。否则校验文件第 3.2 节并解析 manifest。若没有checkpoint对象则不是检查点。强制第 3.1 节的精确布局与第 9 节的兼容性规则。payload: assetspayload 见第 6 节。payload: chunked将 payload 解包到全新目录其中必须包含checkpoint.json此后按存储检查点处理。6. Assets payload版本 4tar 内含路径内容checkpoint/checkpoint.binvCPU 与设备状态state1 字节到 64 MiBcheckpoint/memory.binguest RAMmemory常规或 sparse 条目checkpoint/manifest.binguest 内存布局layout1 字节到 1 MiBcheckpoint/disks/role/index磁盘文件第 4.5 节常规或 sparsecheckpoint/credential-ca.json可选的凭据 CA至多 64 KiBlib/…捕获状态时使用的主机 hypervisor 库agent-rootfs.tar,storage.ext4guest agent 根文件系统与存储模板state、memory、layout必须位于上述确切路径。解包后每个 asset 的长度必须等于其size每个非空sha256必须匹配。state、layout、credential_ca必须具有非空sha256。memory.size至多为memory_mibMiB 加 2 GiB当存在packed_layers时再加上 packed-layer 窗口。state与memory的编码由runtime_abi命名的 hypervisor 库定义对本规范不透明读者使用实现该 ABI 的库来恢复它们。7. 存储检查点Stored Checkpoint存储检查点是一个目录习惯命名为name.checkpointname.checkpoint/ checkpoint.json index of this generation objects/sha256 every object any index here references generations/id/checkpoint.json index of each retained ancestor存储检查点是自包含的它以存储中的硬链接或副本形式持有它及其保留世代引用的每个对象因此无需存储或其他检查点即可恢复。7.1 索引checkpoint.json读者必须拒绝索引及其文件条目中的未知字段。字段类型含义versioninteger1chunk_sizeinteger1048576manifestobjectpack manifest第 4 节其中checkpoint存在filesarray该代的文件files的每个条目字段类型含义pathstring相对路径仅常规组件无..非绝对非空在索引中唯一sizeinteger逻辑长度字节modeinteger权限位只允许设置0o777chunksarray每个 chunk 一项、按序对象哈希或全零 chunk 用nullchunks必须恰好有ceil(size / chunk_size)项。不记录目录、属主或时间戳父目录由路径隐含。索引字段的deny_unknown_fields校验与StoredFile结构定义可参见 crates/smolvm-checkpoint/src/store.rsINDEX常量即checkpoint.jsonCHUNK_SIZE 1024 * 1024。7.2 Chunks 与 objects文件被切分为固定 1 MiB 的 chunk。chunki覆盖字节区间[i × 1 MiB, min(size, (i 1) × 1 MiB))最后一个 chunk 是真实较短的长度。全零 chunk或稀疏文件中无数据的区间记为null且不存储。一个 object 即一个 chunk其名称是未压缩chunk 的 SHA-25664 个小写 hex。其内容是该 chunk 的一个 zstd 帧写入方用 level 3非空至多 1 MiB 128 KiB。读者必须将 object 解压到 chunk 预期长度的精确字节数解码窗口至多 2^23 字节并在使用前将 SHA-256 与其名称比对。恢复文件时设置长度为size写入每个非 null chunknullchunk 读作零。8. 世系与历史8.1 Parent一次捕获记录一个全新的id并以该机器上次被捕获为或恢复自的检查点作为parent。从检查点恢复的机器会记录该检查点的 id 作为自己的位置因此下一次捕获以它作为parent。恢复更早的检查点并再次捕获就会使历史分叉branch不会有任何内容被覆盖。从运行中的机器分叉出的机器继承它的位置。8.2 保留的世代Retained generations存储检查点可以在generations/id/checkpoint.json下保留更早的世代每个都是逐字复制的索引其自身的lineage.id必须等于id不匹配的条目被忽略。smolvm 默认保留至多 32 代含父代本身且绝不超过 256源码中对应常量MAX_RETAINED_GENERATIONS: usize 256。一个检查点的history历史是其自身世代~0然后是其祖先沿parent穿过保留的索引~1、~2、…然后是不在该链上的、任何被保留的世代按created_at最新优先。历史文件的 manifest 以checkpoint.history重复该列表自身世代在前。每个条目是四个lineage字段加data_bytes该世代真实数据——非 null chunk——的字节数。history是描述性的读者从generations/解析世代。8.3 选择世代世代可用以下方式选择~N历史中的第 N 项~0是检查点自身至少 8 个十六进制字符的 id 前缀大小写不敏感必须恰好匹配一个世代。检查点文件版本 4只含一代只有~0可选它。8.4 存储世系记录检查点存储在lineage/id.json中为每个发布进存储的检查点保留记录id、parent、machine、created_at与path发布的目录。这些记录让后续捕获能定位其父代的目录它们是存储索引不属于任何检查点。Rust API 侧对应record_lineage、find_lineage、list_lineage等函数。9. 版本与兼容性读者必须拒绝检查点除非下列全部成立检查项规则版本version恰为4且payload: assets或恰为5且payload: chunked运行时 ABIruntime_abi为libkrun-portable-snapshot-v1主机host_platform与恢复主机完全相等guestplatform的架构与恢复主机匹配设备 profile与是否出现packed_layers匹配CPUcpu_contract接受恢复主机第 4.4 节网络network存在端口合法设置了端口或 backend 则enabled为 true负载若出现非空image、合法overlay_owner、已知restart_policy尺寸cpus与memory_mib非零asset 尺寸符合第 6 节上限磁盘恰为第 4.5 节描述的链版本演进规则如下增加可选字段不算版本变更。读者忽略未知 manifest 字段因此旧读者继续可用。会让旧读者误读的变更才提升version。读者只接受自己实现的版本对其它版本给出明确错误信息而绝不尽力读取。版本 5 的存在意义是先于历史机制出现的读者会拒绝历史文件而不是误读它。检查点可在同一平台、且 CPU 满足其契约的主机之间移植它不能跨操作系统或跨架构移植。10. 安全考虑完整性不等于真实性。CRC-32 与逐对象 SHA-256 检测损坏而非篡改检查点不签名。恢复前应像对待任何可执行构件一样确认检查点的来源——恢复会运行其 guest 状态。检查点可能持有私钥。当出现credential_ca时文件携带机器的凭据 CA包括其私钥。此类检查点应按机密对待。机密不随检查点流转。捕获拒绝带有 secret refs 的机器恢复拒绝 manifest 中含有secret_refs的检查点。凭据绑定只以名称、主机与占位符形式流转值由恢复主机提供。凭据策略是不可信输入。恢复时用与机器创建相同的规则重新校验network.credential_policy。主机绑定状态绝不捕获。捕获拒绝带主机挂载、已发布 socket、远程卷、secret refs、主机支持的镜像层、自定义 DNS、命名机间网络、GPUVulkan 或 CUDA状态、Rosetta、SSH agent 转发或 Docker socket 转发的机器。解包是恶意输入处理。第 3.3 节的路径与链接规则适用于每个 payload包括历史文件。11. 限制汇总项上限manifest16 MiBpayload 解包2,000,000 个条目、128 GiB 声明大小state/layout64 MiB / 1 MiBcredential_ca64 KiB磁盘链64 个文件索引文件256 MiB每个索引的文件数100,000每代字节数2 TiBobject压缩后 1 MiB 128 KiB未压缩 1 MiB保留世代256默认 3212. 写入检查点耐久性指南想要获得 smolvm 同等的持久性保证写入方应将每个 object 写入同目录下的临时文件flush 后以不替换现有名称的方式 rename 到位。以create-new 语义写checkpoint.json并 flush包括保留世代的索引然后 flush 命名它们的目录。通过将暂存目录或文件以no-replace 语义重命名到位来发布检查点Linux 上renameat2(RENAME_NOREPLACE)macOS 上renamex_np(RENAME_EXCL)。已有检查点绝不被覆盖失败的捕获在输出路径不留任何东西。新文件命名为name.checkpoint。这些规则在 Rust 参考实现中均有对应对象先写暂存文件再硬链接进缓存、索引以create_new打开并sync_all、发布走 no-replace 语义见 crates/smolvm-checkpoint/src/store.rs 的finish、publish_pending与publish。另注意其 macOS 特定优化object 级只做普通fsync把一次F_FULLFSYNC设备级整盘 flush推迟到finish通过索引发出避免逐对象整盘刷写拖慢增量捕获。13. 一致性测试与参考实现参考实现的测试固定了上述全部规则包括精确版本拒绝、校验和先于解析、精确容器布局、历史解析~N、id 前缀、歧义、解包路径安全以及在来源目录被删除后从单个历史文件恢复每一代。可运行cargo test -p smolvm-checkpoint cargo test -p smolvm-pack --lib cargo test --lib portable_checkpoint这些测试散落在 crates/smolvm-checkpoint/src/store.rs如对象哈希与既有 SHA-256 对象一致的单元测试、crates/smolvm-checkpoint/tests/consumer.rs验证已发布检查点在旧检查点与缓存被删除后仍可恢复、多次 materialize 互不影响以及 src/portable_checkpoint.rsportable_checkpoint模块测试。14. 参考实现用 Rust crate 读写检查点除格式规范外仓库还提供了独立的存储层 cratesmolvm-checkpoint可在不链接 VM 运行时的情况下使用。其 READMEcrates/smolvm-checkpoint/README.md给出了关键流程在同一文件系统上创建私有暂存目录与一个缓存。创建Writer调用ingest、ingest_tree或ingest_memory。所有源操作成功后调用finish再publish。调用materialize到全新的私有目录以恢复已校验的文件。重复捕获会自动复用未变化的 1 MiB chunk每个检查点以硬链接方式拥有其全部对象删除缓存或旧检查点不会使新检查点失效prune移除无引用的缓存对象删除前先 drop 活动的 writer。复用基于内容兄弟检查点可共享 chunk且每个索引列出自身所需全部对象不要求依赖更早检查点的有序链才能恢复。历史能力对应retain_generations把每个较早世代的索引复制到generations/id/并硬链接其引用的所有对象、materialize_at、resolve_generation、lineage_of存储级注册表用record_lineage/find_lineage/list_lineageexport_with_history把一个检查点与其保留世代打包进单个文件。materialize_with_base可复用经promote_base注册的原始物化不支持的克隆会回退为完整恢复。export产出独立可移植构件。一个完整的最小存储示例在 crates/smolvm-checkpoint/examples/roundtrip.rs可用cargo run -p smolvm-checkpoint --example roundtrip运行。此外有界恢复缓存materialize_cached(directory, output, cache_root, legacy_base, max_entries, max_bytes)以完整检查点索引为键保留原始物化完全重访时克隆匹配检查点而非针对单一上次使用 base 重写变化的 RAM chunk未命中时可对最近条目做差异。缓存按条目数与分配字节做 LRU 限制跨进程由稳定根锁覆盖恢复与淘汰恢复出的文件是私有克隆删除条目不会改动已保存构件或 VM。CLI 默认保留至多 3 个条目、16 GiBmachine create --from与machine checkpoint-warm接受--restore-cache-entries0–64与--restore-cache-gibsmolvm machine checkpoint-warm --from SAVE.smolcheckpoint可只预备增量检查点而不创建或启动机器相关 CLI 参数见 src/cli/machine.rs 与 src/cli/pack.rs。边界与适用前提最后需要强调格式的边界smolvm-checkpoint是存储层不是 hypervisor 或活体 VM 客户端。调用方必须在摄取前使数据静默或打快照并提供一致的 RAM、磁盘与执行状态文件活体捕获、VM 兼容性检查、暂停/恢复与分叉仍在 smolvm 本体如 src/portable_checkpoint.rs中。任意文件加一份 manifest 并不会构成可启动的检查点。存储层仅在 Linux 或 macOS 上使用缓存、暂存与已制备 base 一旦发布就应保持私有且不可变其中可能含凭据与应用内存摄取期间源文件不得变化失败时应丢弃暂存/输出目录而非把部分成果当作检查点。校验和只能检测损坏不能认证不可信检查点的作者。该格式保留 smolvm 现有索引与对象格式也不会让 VM 状态跨不兼容架构或运行时移植。赞分享虚拟化AI Agent人工智能CLI【免费下载链接】smolvmAn embeddable, portable, branchable virtual machine to safely run Agents locally.项目地址https://gitcode.com/gh_mirrors/sm/smolvm点击查看免费下载相关推荐引用格式检查清单引用格式检查清单 所有图表元数据包含完整DOI 新添加图表已同步到Mendeley 引用格式符合团队CSL标准 运行了 citation format valiApache Iceberg 表格式规范format/spec.md完全解读快照、清单、分区变换与行级删除Apache Iceberg 表格式规范format/spec.md完全解读快照、清单、分区变换与行级删除 本文以 Apache Iceberg 仓库中数据湖大数据数据存储Plannotator 可移植指南Portable Guides一个 HTML 文件承载的 Guided Review、v1 快照格式与加密分享Plannotator 可移植指南Portable Guides一个 HTML 文件承载的 Guided Review、v1 快照格式与加密分享 本文讲解上一篇键盘可视化工具 NohBoard让每次按键都变成看得见的直播画面下一篇PKHeX 插件终极实战用 Auto-Legality Mod 一劳永逸搞定合法宝可梦创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑