Skip to content

fix(axvisor): improve multi-VM guest console multiplexing - #1912

Open
YanLien wants to merge 1 commit into
devfrom
fix/guest-console
Open

fix(axvisor): improve multi-VM guest console multiplexing#1912
YanLien wants to merge 1 commit into
devfrom
fix/guest-console

Conversation

@YanLien

@YanLien YanLien commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

问题

AxVisor 同时运行多个 VM 时,各 VM 的串口输出会按字节交错,导致日志内容难以阅读。同时,向某个 VM 输入命令后,其输出可能无法及时显示。

原有的 Ctrl+Alt+h 依赖终端传递修饰键信息,在 Zellij、部分终端及 QEMU 环境中无法可靠识别。

修改内容

  • 启动阶段按完整行显示所有运行中 VM 的串口输出,并添加 [VM n] 前缀。
  • 第一次向 VM 输入后切换到交互模式:
    • 前台 VM 输出直接显示。
    • 后台 VM 输出保存到独立环形日志。
  • 每个 VM 的后台日志上限为 16 KiB,超出后覆盖最旧内容。
  • 切换到后台 VM 时回放其缓存日志,随后恢复实时输出。
  • 使用顺序式 Ctrl+X 快捷键,避免依赖终端增强键盘协议:
    • Ctrl+X h:返回 AxVisor 控制台。
    • Ctrl+X [:切换到上一个 VM。
    • Ctrl+X ]:切换到下一个 VM。
    • Ctrl+X Ctrl+X:向当前 VM 输入原始 Ctrl+X
    • 未知组合会原样传递,不丢失输入。
  • VM 停止、删除或串口后端被替换时,清理对应的输入、输出和前台状态。

实现逻辑

启动阶段仅输出已经完成的逻辑行,避免多个 VM 的分片内容相互穿插。未换行片段暂存在对应 VM 的队列中。

进入交互模式后,当前 VM 获得前台直出权限,其他 VM 的输出写入各自的有界环形日志。切换 VM 时先回放目标 VM 的缓存,再将其设为前台。

主机控制台仍是唯一输入读取方,由多路复用层将普通输入和快捷键事件路由到 AxVisor shell 或对应 VM。

验证

执行:

cargo xtask ktest qemu -p axvisor --test axtest --arch aarch64

结果:

AXTEST_SUMMARY pass=68 fail=0 skip=0 total=68

其中 guest-console 回归测试包括:

  • 14 个输出仲裁和环形日志测试。
  • 18 个多路复用状态机测试。
  • 覆盖 Ctrl+X 快捷键、attach/detach、VM 切换、输入路由、后台日志回放、未换行输出收尾,以及 VM 停止、删除和串口后端替换后的状态清理。

其他验证:

  • cargo fmt --all --check 通过。
  • cargo xtask axvisor build --arch aarch64 通过。
  • AxVisor aarch64 目标配置 Clippy 通过。
  • 双 VM QEMU 场景验证了启动期多 VM 输出、命令输入、前后台切换、缓存日志回放和返回 AxVisor 控制台。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本 PR 将 AxVisor guest console 从简单前台直出扩展为启动期按完整行复用、交互期前台直出/后台有界缓存,并将快捷键改为 Ctrl+X 前缀;同时调整 shell 的 VM attach/detach 流程。

阻塞问题:切回 shell 或切换 VM 时,未换行的前台客户机输出没有在 shell 直写通知前收尾,导致管理 shell 文本与客户机提示符粘连。详见行内评论。

影响范围集中在 AxVisor host console 的输入路由和串口输出仲裁,不涉及 StarryOS syscall/ABI;feature-development.md 的新能力设计门槛不适用(这是现有控制台路径的行为修复/重构)。没有发现基础分支已有等价实现,也没有发现同一 guest-console 的开放 PR;既有 review 和 PR discussion 均为空。

验证:cargo fmt --check 通过,git diff --check 通过;当前头组织 CI 的 Check formatting / run_hostRun clippy / run_host、AxVisor aarch64/riscv64/loongarch64 QEMU(含 smoke)及 x86_64 SVM 检查均成功。Test starry riscv64 qemu / run_container 失败,改动面与 AxVisor console 无关,未作为本 PR 缺陷。按项目指引未重复已通过的 AxVisor CI。额外尝试 cargo test --manifest-path os/axvisor/Cargo.toml --all-features,该宿主命令不启用 bare-metal target 依赖,因 axvm/ax-std 不可解析而失败,不能代表 PR 回归。

测试覆盖:新增 mux 单元测试覆盖缓存、切换与回放,但未覆盖“前台未换行提示符 -> detach/switch -> shell 直接通知”的行为,正是本次缺陷的触发路径。

待办审计:代码、锁顺序、生命周期、输出状态、调用路径、测试发现、CI、历史评论、重复/重叠和行锚均已核查;唯一未解决项为下述输出边界问题。建议先修复并添加回归测试后再复审。

Powered by gpt-5.6-terra

Comment thread os/axvisor/src/guest_console/mux/mod.rs Outdated
b'h' => match state.attached.take() {
Some(vm_id) => {
enqueue_guest_input(&mut state, vm_id, &[ESC, byte]);
state.output.buffer_all();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

严重性:阻塞。这里切回 shell 时只调用 buffer_all() 重置了 physical_line_open,但没有把前台 VM 已经写出的未换行片段收尾。随后 shell 对 Detached 直接 println!,不会经过 mux;例如 VM 提示符为 ~ # 时,用户会看到 ~ # [Axvisor] detached ...,管理 shell 的输出与客户机输出重新粘连。请让退出/切换状态转换在持有输出锁时先输出必要的换行分隔符,并补充包含未换行提示符和 shell 通知的 detach/switch 回归测试。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本 PR 将 AxVisor guest console 扩展为启动期按完整行复用、交互期前台直出/后台有界缓存,并改用 Ctrl+X 前缀快捷键;影响集中在 host console 的输入路由、串口输出仲裁及 VM attach/detach,未改变 StarryOS syscall/Linux ABI。feature-development.md 按语义适用:这是既有共享控制台路径的低风险行为扩展,PR 已说明问题、交互语义和 16 KiB 缓存边界。

代码状态机、输出边界与锁序已审:输出操作统一按 output lock→state 锁序,写 host 前释放 state。上次 review 所指的“未换行 guest prompt 与 shell 提示粘连”在当前 head 已由 buffer_all() 返回换行分隔符并写回 host 的路径修复;该历史评论在当前版本不再成立。

验证:git diff --checkcargo fmt --check 通过;cargo xtask axvisor test qemu --arch aarch64 --test-group normal --test-case smoke 通过(1/1,含 rootfs 自动准备)。当前 head 的组织 CI 为 success=6、skipped=6、cancelled=1,未见失败;取消的是 container spin-lint,跳过项为矩阵/发布条件。当前 CI 没有可确认执行本 PR guest-console 状态机测试的专门 AxVisor case。未重复泛化 clippy,因为当前组织 CI 已通过相关 lint,且本地已运行实际 AxVisor QEMU smoke。

测试覆盖仍有一个阻塞缺口:新增 output 仲裁测试已进入 axtest,但新增 mux 状态机测试没有被可发现的 axtest/QEMU case 或受支持宿主 target 执行,详见行内评论。

重复/重叠:dev 基线没有等价实现;开放 PR 搜索仅命中本 PR。#1909 同样涉及 VM 生命周期但属于 HTTP 管理面,与本 PR 互补,不是重复实现。既有 review thread 的唯一问题已修复。

待办审计:约束、设计适用性、调用链、并发/状态机、测试发现、CI、QEMU 验证、历史评论和重复分析均已完成;唯一未解决项为下述状态机回归测试未接入 runner。请修复后重新请求审核。

Powered by gpt-5.6-terra

Comment thread os/axvisor/tests/axtest.rs Outdated
use axvm as _;

#[path = "../src/guest_console/mux/output.rs"]
mod guest_console_output;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

严重性:阻塞(测试覆盖)。这里仅引入了 guest_console_output,所以 QEMU axtest 只会运行 mux/output.rs 的测试;本 PR 新增的 mux/tests.rs 仍被 #[cfg(test)] 包裹,并未进入 axtest 二进制。该 crate 在宿主 Unix 下也没有可供 cargo test 使用的 axvm/ax-std 目标依赖,因而快捷键、attach/detach、切换和输入路由这些本次改动的状态机测试实际上不会被项目 runner 执行。请把 mux 状态机回归测试接入当前 axtest/QEMU 流程(或提供受支持的宿主测试 target),并验证具体用例确实被执行。

@YanLien
YanLien force-pushed the fix/guest-console branch from ecbbcdd to ac59f4b Compare August 7, 2026 06:36

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本 PR 将 AxVisor guest console 扩展为:启动期按完整行复用、多 VM 交互期前台直出/后台 16 KiB 环形缓存,并以顺序式 Ctrl+X 快捷键处理 attach/detach/切换;改动集中在 host console 的输入路由、串口输出仲裁和 VM 生命周期,不涉及 StarryOS syscall/Linux ABI。

feature-development.md 适用:这是既有共享控制台路径的低风险行为扩展。实现通过 output lock→state lock 的固定顺序协调输出和状态,并在 detach/switch 时用 buffer_all() 收尾未完成物理行;此前关于 shell 文本与 guest 未换行提示符粘连的评论已由当前 head 的换行输出路径修复。

验证:git diff --check、本地 cargo xtask ktest qemu -p axvisor --test axtest --arch aarch64 均通过;后者实际得到 AXTEST_SUMMARY pass=68 fail=0。组织 CI 的格式化、lint 和 AxVisor 相关检查已核对;被跳过/取消的矩阵项不是本次 guest-console 改动的失败证据,因此未重复广泛本地测试。当前 QEMU axtest 命令也证明 axtest 构建、发现和运行链路本身可用。

但新增核心状态机测试没有进入该链路,见行内评论。现有 QEMU 成功只覆盖已有 axtest case,不能证明 Ctrl+X 路由、attach/detach、切换及生命周期清理在回归时会被检测。请修复并让具体 mux case 出现在 axtest 输出后重新请求审核。

重复/重叠:dev 基线没有等价实现;开放 PR 搜索仅命中本 PR。#1909 触及 VM 生命周期但属于 HTTP 管理面,和本 PR 互补。此前两条 review 里,未换行输出边界问题已解决;测试接入问题仍未解决。待办审计已完成,唯一阻塞项如下。

Powered by gpt-5.6-terra

}

#[path = "../src/guest_console/mux/mod.rs"]
mod guest_console_mux;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

严重性:阻塞(回归测试未实际执行)。这里虽然把 mux/mod.rs 纳入了 axtest 二进制,但该文件对新增状态机用例仍使用 #[cfg(test)] mod tests;;无 harness 的 axtest 构建只设置 cfg(axtest),不会设置 cfg(test)。因此 mux/tests.rs(以及 output.rs 内同样被 cfg(test) 包住的用例)没有被编译或注册,#[cfg_attr(axtest, axtest::axtest)] 也无法生效。我在当前 head 运行 cargo xtask ktest qemu -p axvisor --test axtest --arch aarch64 虽得到 AXTEST_SUMMARY pass=68 fail=0,但输出没有任何 guest_console_mux case,编译诊断还把该模块列为未使用。这样 Ctrl+X 路由、attach/detach、切换和生命周期清理这些本 PR 的核心状态机没有可执行回归覆盖。请将测试模块改为同时在 testaxtest 下编译(例如 #[cfg(any(test, axtest))]),或在 tests/axtest.rs 直接注册这些用例,并重新运行 QEMU axtest 来证明具体 case 被执行。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant