工程说明¶
从仓库根目录运行命令。just 列出支持的任务,每种工作流保留一个入口。
仓库结构与代码归属¶
Cargo workspace 包含按产品职责划分的 13 个 crate,默认成员是 pvisor-cli。Python pvisor/ 是可安装的版本标记,不是启动器或运行时实现。
wheel 将原生可执行脚本直接安装到环境的 bin 目录;旧 Python 启动器及其二进制覆盖方式已废弃。
| 目录 | 职责 |
|---|---|
crates/pvisor/ |
可嵌入运行时、Session/Attempt 编排、执行器、持久化 Job 服务、镜像准备和缓存机制 |
crates/pvisor-cli/ |
四个应用二进制、CLI 命令、终端前端和 replay/TUI 伴随程序分派 |
crates/pvisor-vm/ |
原生 VM 运行时、跨平台 API、私有 VMM/平台实现、内嵌 guest 和内核/固件接入 |
crates/pvisor-daemon/ |
Linux x86_64 sandbox 生命周期 API、独立原生 VM supervisor 和可选 daemon 自有池 |
crates/pvisor-core/ |
Operation、Placement、策略、对外交互和 Event 契约 |
crates/pvisor-journal/ |
共享事实 Journal 存储与读取 |
crates/pvisor-gateway/ |
Agent 协议转发、转换、采集与投影 |
crates/pvisor-overlay-core/ |
不依赖 FUSE 的 OverlayFS 操作和文件访问控制 |
crates/pvisor-overlayfs/ |
FUSE 适配及挂载 |
crates/pvisor-overlaynet/ |
出站策略、HTTP 代理和 VM virtio-net 数据通路 |
crates/pvisor-guest/ |
Linux PID 1 supervisor,以及 VM 执行器共用的启动契约 |
crates/pvisor-shim/ |
containerd Runtime v2 shim,可选 VM 执行 |
crates/pvisor-replay/ |
回放规划、原生 Agent 适配器和续跑协议桥 |
pvisor/、setup.py、scripts/packaging/ |
Python 版本标记和原生脚本 wheel 打包 |
crates/*/tests/ |
Rust 集成测试;单元测试跟随所属模块 |
tests/ |
Python 打包和仓库工作流测试 |
examples/、benchmark/ |
可运行的产品场景和性能测量 |
scripts/ci/ |
CI 检查及冒烟测试入口 |
docs/src/zh/、docs/src/en/ |
文档源;docs/site/ 是生成产物 |
vendor/ |
有补丁的第三方依赖;产品编排逻辑放在 crates/ |
workspace 内的直接普通依赖关系(包含目标平台限定的边;以下名称省略 pvisor- 前缀):
cli ──> pvisor, core, journal, replay, overlaynet, overlay-core, vm
pvisor ──> core, journal, overlaynet, overlayfs, overlay-core, guest, vm
cli --features gateway ──> gateway, pvisor/gateway
pvisor --features gateway ──> gateway
vm ──> overlay-core
daemon ──> pvisor, core
replay ──> core, journal
shim ──> guest, overlay-core
shim --features vm ──> vm
gateway ──> core, journal, overlaynet
overlaynet ──> core
overlayfs ──> core, overlay-core
overlay-core ──> core, journal
journal ──> core
core, guest ──> 不依赖其他 workspace crate
pvisor 没有 CLI 或 Clap 普通依赖;Clap 仅作为示例使用的开发依赖。
pvisor-replay 引擎没有对 pvisor 或 Clap 的普通依赖。
pvisor-tui crate 已移除,其可执行文件名称不变。
pVisor 源码模块¶
crates/pvisor-cli/src/
├── lib.rs # 前端模块,不重导出运行时
├── bin/ # 四个:pvisor、pvisor-cache、pvisor-tui、pvisor-replay
├── cli/ # 参数、命令和共享终端工具
│ ├── cache.rs # 缓存参数解析与展示
│ └── features.rs # 运行时功能列表前端
├── companions.rs # 同一安装中的伴随程序查找/分派
└── tui/ # TUI PTY 运行时、渲染、审查面板和按键映射
crates/pvisor/src/
├── lib.rs # 运行时导出与显式前端/嵌入 API
├── session/ # Attempt 生命周期与收尾
├── session.rs # Session 所有者
├── config.rs # 运行时与执行器配置
├── trace.rs # 共享事实 Journal 重导出
├── diagnostics.rs # 共享宿主日志,前端选择输出位置
├── executor/
│ ├── mod.rs # RunExecutor 和执行输出契约
│ ├── process.rs # 宿主进程执行器
│ ├── container.rs # 容器执行器
│ ├── sandbox.rs # 宿主 OS 隔离及内部 sandbox 入口
│ ├── artifact.rs # 适配 guest 的可执行文件解析
│ ├── delegated.rs # 委派执行的 spec/result 交接
│ └── vm/ # VM 执行器适配与 Run 资源/控制接入
├── image/
│ ├── oci.rs # Registry、准备记录、blob 和解包
│ └── cache/ # 缓存协议、服务端、客户端及懒加载 FUSE
├── runtime/
│ ├── run.rs # PVisor API 和运行生命周期
│ ├── job_service.rs # 持久化 RuntimeJobService
│ ├── job_execution.rs # Job 执行机制
│ ├── host_transport.rs # 类型化 Host 传输
│ ├── instance_control.rs # 本地实例控制交互
│ ├── agentctl.rs # 每次运行的协作控制服务
│ ├── agentctl_client.rs # 同步 AgentCtl 客户端
│ ├── audit.rs # 审批 socket 传输与缓存
│ ├── event.rs # 运行事件发布
│ ├── bundle.rs # 持久化审查摘要
│ ├── checkpoint.rs # 逻辑检查点与恢复
│ ├── registry.rs # Run 身份、存活锁和本地控制端点
│ ├── attempt.rs # 每次尝试的驱动资源与清理
│ ├── supervisor.rs # 能力检查与驱动协调
│ ├── operation.rs # 操作与观察构造
│ ├── implant.rs # 运行环境注入
│ ├── overlay.rs # 暂存、审查、应用/丢弃和恢复
│ └── zcode.rs # 进程兼容策略
└── util.rs # 少量共享文件与时间工具
CLI 参数与展示、Host 监听器/worker 归 pvisor-cli;
具体执行机制归 pvisor 的 executor/,Run 资源所有权和持久化 Job 服务归 runtime/。
VM 执行器将 Run/Attempt 生命周期适配到 pvisor_vm::api;VMM、平台机制、内嵌 guest
和内核/固件接入属于 pvisor-vm。OCI 准备属于 image/,供直接加载和缓存服务共用。
缓存存储及带认证的服务端留在运行时,缓存命令解析/展示归 pvisor-cli/src/cli/cache.rs。
Bundle 和检查点与运行记录放在一起,不归某个执行后端。pvisor-daemon/src/memory_pool.rs 拥有池启动/复用和独立 memory-pool 组件;通过 serve --memory-pool 启用。pvisor/src/node.rs 与 node/ 中的 node 协议是运行时设施,没有 daemon acquire/release 适配器。pvisor-cache 保留独立准备、发布、服务和读取入口。
既有公开运行时导入,包括 PVisor、ProcessExecutor、cache 以及内部 sandbox 入口,
保留原有路径。显式前端/嵌入 API 导出文件访问类型、GatewayProfile、
DelegatedRunOutput、rootless_runtime_available、Overlay 选择/检查及 Run 查找/控制工具、
Linux Run 租约、audit、checkpoint、job_execution 和启动标记/私有 JSON 工具。
运行时实现模块仍保持私有;这些导出不构成 API 稳定性承诺。
replay 中,adapter/ 负责原生轨迹规划和 Agent 启动选择;bridge/ 负责
Claude、Codex、OpenCode 协议桥及 Claude resume transport 校验。
共享执行和 journal 仍在 crate 根目录。
核心实现边界¶
core 定义 Operation、Event 和共享策略;pvisor 实现准入、实际改写、Placement 和调度。 Session 统一拥有 Attempt 的资源与终态;执行器负责执行并返回观察,OverlayCore 负责文件应用与恢复。 AgentCtl 与审批 socket 的实际 I/O 留在 pvisor。完整职责见核心架构, 字段和事件顺序见 Operation 与 Event。
核心减法预算¶
CI 先检查默认运行时和应用的依赖边界,再构建带捕获的分发包。scripts/ci/check_core_budget.py
拒绝 CLI、Gateway、replay、Clap、TUI 和终端依赖进入 pvisor 的普通依赖闭包。
默认 pvisor-cli 应用包含 replay 引擎和集成 TUI,Gateway 仍为可选。
脚本记录工具链、运行时/应用依赖数、运行时闭包源码行数、Core 公开声明数和应用二进制字节数。预算及统计口径由脚本维护;实测结果保存在 CI 报告中,
比较时使用相同平台和工具链。
贡献者命令¶
| 命令 | 作用 |
|---|---|
just build / just build release |
构建 debug/release CLI,并在 macOS 上签署 Hypervisor entitlement |
just install-cli |
将已签名的 release CLI 安装到 CARGO_INSTALL_ROOT 或 ~/.cargo |
just wheel / just wheel debug |
构建全新 wheel,通过安装验证后再放入 dist/ |
just check |
检查产品及其依赖能否通过编译检查 |
just fmt / just fmt-check |
格式化 Rust/Python 源码,或仅检查格式 |
just lint |
运行 Clippy 和 Python 包 lint 检查 |
just test |
通过 nextest 跑工作区 Rust 测试,再跑 Python 测试 |
just test core pvisor cli |
测试指定 Rust 包:共享契约、运行时和应用 |
just test cli / just test pvisor-cli |
可执行文件/前端测试;just test pvisor 选择运行时测试 |
just test pvisor-vm |
VM 所有者测试;macOS 在 nextest 前签署 Hypervisor entitlement |
just test-py -k packaging |
将选项传给 pytest |
just test-benchmark |
用 pytest 单独运行 benchmark 工具测试;默认 Python 测试已包含这些检查 |
just test-py --vm-bin target/release/pvisor |
启用真实 VM 的普通终端和 TUI 交互回归 |
just test-py tests/test_zcode_integration.py --zcode-integration |
显式运行需要 Linux rootless、FUSE3 和 zcode 的集成测试 |
just test-isolation |
运行严格的 Linux rootless/FUSE 回归,不跳过缺失的用户命名空间能力 |
just smoke |
构建 debug CLI 并检查主要命令入口 |
just examples |
构建 release CLI 并运行全部示例;追加场景名可选择子集 |
just cases --case S-DOC-001,S-DOC-002 |
运行选定的文档场景 |
just benchmark / just benchmark nightly |
运行进程与 Run Bundle 基准 |
just docs-build |
构建双语文档并检查链接 |
just docs-serve / just docs-serve en |
Zensical 原生预览与自动刷新;中文端口 3000,英文端口 3001 |
just ci |
检查格式、lint、测试并构建,不改写源码 |
just clean |
清理构建产物,保留开发环境和本地 Run 记录 |
just test 和 just test-rust 支持 Cargo 包名,以及 pvisor、cli(pvisor-cli)、core、
control/agentctl(Core 的兼容别名)、capture(Gateway)、shim(pvisor-shim)这些简称。
带参数的 just test 只运行指定 Rust 包的测试。CI 分片使用 just test-rust,
不会额外触发 Python 测试。
仅使用运行时的 Rust 测试留在 crates/pvisor/tests/。
19 个可执行文件/前端集成测试文件(包括混合运行时与命令测试)现归 crates/pvisor-cli/tests/;
混合文件中的纯运行时用例仍保留在 pvisor。
原生 VM 和依赖环境的测试保留原有前置条件及跳过/ignore 门槛;编译检查不代表真实 guest 验证。
默认 pytest 收集 tests/ 和 benchmark/pvisor/;共享 Operation 和 Overlay 契约由 pvisor-core 的 Rust 测试验证。
benchmark 中依赖 /proc 和 Linux rootfs 工具的测试仅在 Linux 上运行。
VM 文件系统检查在 Linux guest 内运行,需要 root、Python、pytest 和 tar;
在仓库目录执行 python3 -m pytest -q tests/test_vm_filesystem.py --guest-fs-dir /var/tmp --guest-fs-dir .,
分别检查 guest 根文件系统与挂载工作区。未指定目录时跳过,显式启用后检查失败会报错。
需要指定 Rust 集成测试或过滤条件时,直接调用 nextest,例如:
cargo nextest run --locked -p pvisor-gateway --test llm_fixtures。
nextest 不运行 doctest;需要时使用 cargo test --doc -p <package>。
CI 分工¶
| 工作流 | 触发条件与职责 |
|---|---|
| CI | 面向 main 和 develop 的 push/PR:格式、Clippy、actionlint、Python 测试、基准工具测试、Rust 测试、文档用例与示例 |
| Documentation | 文档变更:双语构建与链接检查;仅上游仓库的 main 部署 Pages |
| pVisor Benchmark | 运行时、构建或基准变更:与 PR 基线或前一提交比较并上传报告 |
| Nightly Build | 每日或在 main 手动触发:构建、校验双平台 wheel,更新 nightly release |
| Publish PyPI | 稳定版本 tag:检查版本、lockfile 和 main 祖先关系后构建发布;手动运行只构建校验 |
保留必需状态 CI:任一依赖失败、取消或跳过都会使其失败。Linux Rust 测试按
core、Gateway、pVisor 分片,macOS 对同一组包只跑一遍。独立 Linux 隔离任务
必须具备 user namespace 和 FUSE,不允许跳过隔离检查。文件系统示例与文档用例共用该任务的
release 构建和隔离环境。网络/Gateway 示例在单独任务运行。
共享 action 默认只安装 Python、uv 和 just;Rust、nextest 和 guest Rust target 按需启用。Linux 静态 CLI/shim 构建通过
static-musl 启用 Zig 和 cargo-zigbuild;Rust 检查和单元测试不需要这两个工具。
双平台 wheel 矩阵集中在一个可复用工作流中。PR 文档构建不会取消 Pages 部署。
VM guest 启动¶
pvisor-guest 同时提供共享的 GuestConfig 库和 pvisor-guest 可执行文件。
构建 pvisor-vm 的 init-blob feature 时,crates/pvisor-vm/build.rs 使用 Rust 自带
rust-lld,按 VM 架构把 guest 编译成 release Linux musl ELF。
独立的 target/pvisor-guest/ 目录避免与外层 Cargo 构建争抢产物锁。
libkrun 内嵌该 ELF,暴露为 /init.krun,由它担任 guest PID 1。
CLI 和 shim 注入 /.pvisor-guest.json,传递 argv、环境变量、cwd、工作区挂载、
资源限制、可选网络配置和 shim agent 参数。supervisor 初始化 guest 文件系统和
控制台 I/O,挂载工作区、配置网络、直接启动工作负载并回收子进程。
退出时先通过 libkrun 私有的根文件系统 ioctl 0x7602 上报工作负载退出码,
再 sync/reboot。非零退出码使 Attempt 失败;VM 正常关机但未上报退出码时按 125 失败。
启动性能实测及测量范围见 Guest init comparison。
打包与命名¶
Python 包、安装后的 CLI 和运行时 Rust crate 使用 pvisor;应用 crate 为 pvisor-cli,伴随 crate 使用 pvisor-*,
环境变量使用 PVISOR_*。wheel 文件名形如 pvisor-<version>-py3-none-<platform>.whl。
构建环境¶
仓库使用 rust-toolchain.toml 中的 stable 工具链、默认 LLVM backend 和平台 linker。
请安装 nextest 0.9.137,或使用仓库 CI setup action。guest supervisor 使用 Rust 自带 linker 构建成静态 Linux musl ELF;macOS VM 构建不需要 Zig。
Apple Silicon 上首次构建前执行 rustup target add aarch64-unknown-linux-musl。
CI 仅安装当前架构的 guest target,工作区工具链不为无关 crate 下载交叉编译 target。
| 产物 | Linux | Apple Silicon macOS |
|---|---|---|
| 宿主 CLI | 静态 Linux musl ELF | 原生 Darwin 可执行文件,签署 HVF entitlement |
| 内嵌 guest | 静态 Linux musl ELF | 静态 Linux musl ELF |
pvisor-vm |
单一 Rust 运行时 crate | 单一 Rust 运行时 crate |
| guest 内核 | 构建时内嵌 | 运行时加载 libkrunfw.5.dylib |
CARGO_TARGET_DIR 指定原生构建目录,构建、安装、smoke、示例和场景任务共用此位置。
wheel 使用全新的暂存目录进行验证,避免误把 dist/ 中的旧包当作本次产物。
Linux CLI 全静态链接 musl 并内嵌 VM 内核。构建需要 Zig、cargo-zigbuild 和
rustup target add x86_64-unknown-linux-musl。Linux wheel 保留 manylinux_2_28
标签以支持 glibc Python 安装器。
文档任务通过 uv 隔离环境使用与 CI 相同的锁定版 Zensical,无需单独维护文档虚拟环境。
发布流程见发布 PolicyVisor,运行时要求见可复现示例。
私有运行时模块在 libkrun 1.19.3 基线上选择性回移植上游改进。来源提交、本地适配与验收限制见上游同步记录;版本号不代表已完整升级到 1.19.6 或 2.0。
VM API 边界¶
pvisor_vm::api 是运行时唯一的外部接口。它声明跨平台 struct 和 trait 方法签名,不包含条件编译或方法体。私有模块实现契约;调用方导入需要的 VmConfiguration、VmRuntime、VmControl 以及快照/RAM trait。平台服务由 VmPlatform 的 RuntimeSupport 提供。
CLI、shim、示例和 init 基准使用这套接口。寄存器/设备测试及硬件探针归属 pvisor-vm 内部。静态内核提取与打包由以下文件负责: crates/pvisor-vm/build_kernel.rs;既有构建环境变量兼容。固件数据 ABI 和操作系统 FFI 保持私有。历史 trace/receipt 标识和基准证据保留原名。
运行 just test pvisor-vm;macOS 使用既有 Hypervisor entitlement 签署其测试程序。真实 VM 测试需要宿主 HVF/KVM 权限;Linux 创建 VM 的测试需要 /dev/kvm。