axvisor_api_proc
路径:
virtualization/axvisor_api_proc类型:过程宏库 分层:组件层 / 编译期 API 生成辅助 版本:0.1.0文档依据:当前仓库源码、Cargo.toml、README.md、src/lib.rs、src/items.rs、virtualization/axvisor_api/src/lib.rs、virtualization/axvisor_api/src/test.rs
axvisor_api_proc 不是运行时 API 库,而是 axvisor_api 背后的过程宏辅助 crate。它的职责是把一组带 extern fn 语法标记的模块,展开成可调用的 API 包装函数和对应的 crate_interface trait/impl 胶水代码。因此它属于“编译期 glue”,而不是 Hypervisor 子系统本体。
架构设计
设计定位
这个 crate 解决的是 Axvisor API 组织方式问题:
- 如何让“定义 API 的模块”写起来像普通 Rust 模块
- 如何让“实现这些 API 的模块”在另一个位置编写
- 如何在编译期自动生成跨模块绑定代码
其公开入口只有两个属性宏:
#[api_mod]#[api_mod_impl(path)]
这说明它的本质是一套模块级 API DSL,而不是运行时组件。
1.2 语法模型
src/items.rs 定义了宏要解析的核心语法节点:
| 类型 | 作用 |
|---|---|
ItemApiFn<T> | 表示一个 API 函数;定义态用 ;,实现态用 Block |
ApiModItem<T> | 模块中的条目,区分普通 item 和 API 函数 |
ItemApiMod<T> | 带有 API 语义的模块定义 |
ItemApiModDef | #[api_mod] 使用的定义态模块 |
ItemApiModImpl | #[api_mod_impl] 使用的实现态模块 |
这里最关键的设计是:
- API 函数用
extern fn ...;或extern fn ... { ... }作为标记 - 普通 item 则原样保留
这样宏就能在一个模块里同时容纳:
- 类型别名
use/pub use- 普通辅助函数
- 真正需要跨组件绑定的 API 函数
1.3 api_mod 的展开思路
#[api_mod] 处理的是“定义 API”的模块。其关键步骤是:
- 解析输入模块
- 把模块内容分成普通条 目和 API 函数
- 生成一个隐藏 trait,名字形如
Axvisor{Module}ApiTrait - 给每个 API 函数生成一个同名包装函数
- 包装函数内部用
crate_interface::call_interface!转调
这些隐藏 trait 不是直接引用 crate_interface 路径,而是通过:
axvisor_api::__priv::crate_interface
来拿到 def_interface / call_interface,从而避免调用方必须手工了解底层依赖布局。
1.4 api_mod_impl 的展开思路
#[api_mod_impl(path)] 处理的是“实现 API”的模块。其关键步骤是:
- 解析被实现模块的路径
- 复用该路径并生成一个隐藏别名,避免 trait 路径找错
- 收集实现态模块里的
extern fn - 生成一个隐藏结构体
__Impl - 用
crate_interface::impl_interface为对应 trait 生成实现
这说明 axvisor_api_proc 本质上不是在“注册 handler”,而是在替调用方生成 trait + 调用桥 + 实现桥。
1.5 关键约束
源码已经把这套 DSL 的边界写得很清楚:
api_mod不接受任何参数api_mod只支持内联模块,不支持mod foo;这种 outlined module- API 函数不能带
self接收者 axvisor_apicrate 必须能被找到,否则直接生成compile_error!
这些限制都不是偶然的,而是为了让宏展开后的 trait 绑定保持简单和稳定。
1.6 与 axvisor_api 的真实关系
virtualization/axvisor_api/src/lib.rs 直接:
pub use axvisor_api_proc::{api_mod, api_mod_impl};
并用这两个宏定义了 memory、time、vmm、host、arch 等 API 模块。随后:
arm_vcpuarm_vgicaxdeviceaxvmaxvmriscv_vcpuriscv_vplicx86_vcpuos/axvisor
等 Axvisor 相关组件通过 axvisor_api 间接依赖这套宏展开结果。
因此,axvisor_api_proc 的真实地位是:Axvisor API 组织方式的编译期基础设施。
核心功能
功能概览
- 解析带
extern fn标记的 API 模块 - 为 API 模块生成隐藏 trait
- 为 API 定义侧生成包装调用函数
- 为 API 实现侧生成
__Impl和 trait 实现 - 通过
proc_macro_crate自动定位axvisor_apicrate 路径
2.2 真实调用链
真实的使用链路是:
axvisor_api用#[api_mod]定义 API 模块- 宏展开后得到普通函数 + 隐藏 trait
- 某个实现模块用
#[api_mod_impl(...)]生成实现 - 调用方像调用普通函数一样调用
axvisor_api::memory::alloc_frame()等接口 - 底层再通过
crate_interface完成绑定
这条链路里,axvisor_api_proc 只参与第 1 到第 3 步,且全部发生在编译期。
2.3 最关键的边界
axvisor_api_proc 不提供:
- 运行时 API 注册表
- 动态查找或插件机制
- 真正的内存/时间/中断实现
- Hypervisor 状态管理
它只负责把一套模块语法展开成编译期胶水代码。
依赖关系
直接依赖
| 依赖 | 作用 |
|---|---|
syn | 解析模块和函数语法树 |
quote | 生成展开代码 |
proc-macro2 | token 处理 |
proc-macro-crate | 定位 axvisor_api 在当前依赖图中的真实路径 |
主要消费者
直接消费者:
axvisor_api
通过 axvisor_api 间接接入的主要组件:
arm_vcpuarm_vgicaxdeviceaxvmaxvmriscv_vcpuriscv_vplicx86_vcpuos/axvisor
3.3 关系解读
| 层级 | 角色 |
|---|---|
axvisor_api_proc | 编译期属性宏生成器 |
axvisor_api | 对外 API 门面 crate |
| 各虚拟化组件 | 通过 axvisor_api 使用展开后的接口 |
开发指南
4.1 什么时候应该改这个 crate
只有在以下情况才应直接修改:
api_mod/api_mod_impl的语法要扩展- 展开后的 trait 或包装函数要调整
axvisor_apicrate 名解析策略要修正- 需要改进错误诊断或文档生成
如果只是新增一个 Axvisor API,通常应该改 axvisor_api/src/lib.rs 或对应实现模块,而不是改宏 crate 本身。
4.2 维护时最容易出错的点
items.rs的语法定义与lib.rs的展开逻辑必须同步api_mod和api_mod_impl使用的 trait 命名规则必须一致- 被实现模块路径的复用标识不能丢,否则生成的
impl可能找不到 trait extern fn是 DSL 标记,不是普通 FFI 语义,相关文档必须讲清楚