ArceOS 开发指南
ArceOS 既是可以单独运行的模块化 Unikernel,也是 StarryOS 与 Axvisor 共享的基础能力层。本文档面向在 TGOSKits 工作区内进行 ArceOS 相关开发的场景,覆盖开发环境、模块开发规范、应用与平台开发、测试策略、调试技巧和跨架构验证。
1. 开发环境
1.1 工具链
TGOSKits 工作区根目录的 rust-toolchain.toml 已锁定统一工具链:
| 配置项 | 值 |
|---|---|
| channel | nightly-2026-04-27 |
| profile | minimal |
| components | rust-src, llvm-tools, rustfmt, clippy |
| targets | x86_64-unknown-none, riscv64gc-unknown-none-elf, aarch64-unknown-none-softfloat, loongarch64-unknown-none-softfloat |
进入工作区后 rustup 会自动切换到该工具链,无需手动配置。
1.2 QEMU
ArceOS 开发和测试依赖 QEMU system emulator:
| 架构 | QEMU 包名 | 验证命令 |
|---|---|---|
| aarch64 | qemu-system-aarch64 | qemu-system-aarch64 --version |
| riscv64 | qemu-system-riscv64 | qemu-system-riscv64 --version |
| x86_64 | qemu-system-x86_64 | qemu-system-x86_64 --version |
| loongarch64 | qemu-system-loongarch64 | qemu-system-loongarch64 --version |
推荐版本 ≥ 10.2.1。Debian/Ubuntu 安装示例:
sudo apt install qemu-system-arm qemu-system-riscv64 qemu-system-x86
1.3 交叉编译工具链(可选)
大部分场景下 cargo + rust-src 即可完成 no_std 交叉编译,无需额外交叉工具链。仅当模块依赖 C 代码或需要链接外部 .a 时,才需安装对应的 gcc 交叉编译器。
2. 目录结构总览
os/arceos/
├── modules/ # 内核模块
│ ├── axhal/ # 硬件抽象层
│ ├── axtask/ # 任务/线程管理 + 调度器
│ ├── axalloc/ # 内存分配器
│ ├── axdriver/ # 统一设备驱动框架
│ ├── axfs/ # 文件系统(legacy)
│ ├── axfs-ng/ # 文件系统(next-gen, ext4/fat)
│ ├── axlog/ # 多级日志
│ ├── axsync/ # 同步原语
│ ├── axmm/ # 页表/内存管理
│ ├── axdisplay/ # 图形显示
│ ├── axdma/ # DMA 支持
│ ├── axinput/ # 输入设备
│ ├── axipi/ # 核间中断
│ ├── axruntime/ # 运行时初始化,调用 main()
├── api/ # 对外 API 层
│ ├── axfeat/ # 顶层 feature 聚合(单一真相源)
│ ├── arceos_api/ # 公共 API 和类型
│ └── arceos_posix_api/ # POSIX 兼容 API
├── ulib/ # 用户侧库
│ ├── axstd/ # Rust std 风格接口
│ └── axlibc/ # C libc 接口
net/
└── ax-net/ # 统一网络栈(TCP/UDP/raw/Unix/vsock/DNS/DHCP)
apps/arceos/
├── helloworld/
├── httpserver/
├── httpclient/
├── io_test/
├── thread_test/
├── tokio_test/
├── arce_agent/
└── shell/
3. 模块开发
3.1 模块标准结构
以 axtask 为代表的典型模块结构:
modules/axtask/
├── Cargo.toml # features + 依赖
└── src/
├── lib.rs # 模块根,条件编译,re-exports
├── api.rs # 公共 API 函数
├── task.rs # Task 结构体
├── run_queue/ # 调度器 run queue 实现
└── wait_queue.rs
关键约定:
lib.rs:使用cfg_if!和#[cfg(feature = "...")]进行条件编译,通过pub use向外暴露公共 APIapi.rs:存放面向应用的公共函数,如spawn(),sleep(),yield_now()- init 函数:模块暴露
init_*()函数,由axruntime::rust_main()在启动时根据 feature 配置调用
典型的 init 调用链(axruntime 中):
// axruntime/src/lib.rs (简化)
pub unsafe fn rust_main() {
ax_log::init();
ax_hal::platform_init();
ax_alloc::init();
#[cfg(feature = "paging")]
ax_mm::init();
#[cfg(feature = "multitask")]
ax_task::init_scheduler();
#[cfg(feature = "fs-ng")]
ax_fs_ng::init_filesystems(/* ... */);
#[cfg(feature = "net")]
ax_net::init_network(/* ... */);
// ...
main();
}
3.2 开发一个新模块
假设要添加 axmymod 模块,步骤如下:
1) 创建目录和文件
os/arceos/modules/axmymod/
├── Cargo.toml
└── src/
├── lib.rs
└── api.rs
2) 编写 Cargo.toml
[package]
name = "ax-mymod"
version.workspace = true
edition.workspace = true
[dependencies]
ax-feat = { path = "../../api/axfeat" }
log = "0.4"
[features]
default = []
myfeature = []
3) 编写 lib.rs
#![no_std]
extern crate log;
mod api;
pub use api::*;
4) 编写 api.rs,暴露 init 函数和公共 API
use log::info;
pub fn init() {
info!("axmymod initialized.");
}
pub fn do_something() -> i32 {
42
}
5) 在 axruntime 中接入 init 调用
在 os/arceos/modules/axruntime/src/lib.rs 的 rust_main() 中添加:
#[cfg(feature = "mymod")]
ax_mymod::init();
6) 在 axfeat 中注册 feature
在 os/arceos/api/axfeat/Cargo.toml 中添加:
[features]
mymod = ["dep:ax-mymod", "ax-runtime/mymod"]
[dependencies]
ax-mymod = { path = "../../modules/axmymod", optional = true }
7) 验证
cargo xtask arceos qemu --package arceos-helloworld --arch aarch64 --features mymod
3.3 Feature 驱动编译
ArceOS 的核心设计是 feature 聚合:应用在 Cargo.toml 中声明需要的 feature,axfeat 将它们传播到对应模块。
axfeat 中的 feature 定义示例(简化):
[features]
# CPU
smp = ["alloc", "ax-hal/smp", "ax-runtime/smp", "ax-task?/smp"]
fp-simd = ["ax-hal/fp-simd"]
# 内存
alloc = ["ax-alloc", "ax-runtime/alloc"]
paging = ["alloc", "ax-hal/paging", "ax-runtime/paging"]
# 任务
multitask = ["alloc", "ax-task/multitask", "ax-sync/multitask", "ax-runtime/multitask"]
sched-fifo = ["ax-task/sched-fifo"]
sched-rr = ["ax-task/sched-rr", "irq"]
sched-cfs = ["ax-task/sched-cfs", "irq"]
# 上层协议栈
fs = ["alloc", "paging", "ax-driver/virtio-blk", "dep:ax-fs", "ax-runtime/fs"]
net = ["alloc", "paging", "ax-driver/virtio-net", "dep:ax-net", "ax-runtime/net"]
这意味着:
- 启用
smp会自动启用alloc并传播到ax-hal、ax-runtime、ax-task - 启用
net会自动拉起 alloc + paging + virtio-net 驱动 + ax-net 模块 - 应用只需关心自身需要的功能,不需要了解底层模块的依赖图
3.4 修改已有模块
修改已有模块时的推荐流程:
| 改动类型 | 验证命令 | 扩展验证 |
|---|---|---|
基础 crate(axerrno, kspin, page_table_multiarch) | cargo test -p <crate> | cargo xtask arceos qemu --package arceos-helloworld --arch riscv64 |
HAL(axhal) | cargo xtask arceos qemu --package arceos-helloworld --arch aarch64 | 多架构验证 |
调度器(axtask) | cargo xtask arceos qemu --package arceos-helloworld --arch riscv64 | cargo xtask arceos test qemu --target riscv64gc-unknown-none-elf |
网络(axnet / axnet) | cargo xtask arceos qemu --package arceos-httpserver --arch aarch64 --net | 检查 TCP 连接和吞吐 |
文件系统(axfs / axfs-ng) | cargo xtask arceos qemu --package arceos-shell --arch aarch64 --blk | 检查文件读写 |
驱动(axdriver) | cargo xtask arceos qemu --package arceos-helloworld --arch aarch64 | 启用对应设备 --blk / --net |
4. 应用开发
4.1 新增 Rust 示例应用
1) 创建目录和文件
apps/arceos/myapp/
├── Cargo.toml
└── src/
└── main.rs
2) Cargo.toml
[package]
name = "arceos-myapp"
version = "0.1.0"
edition.workspace = true
[features]
default = []
arceos = ["dep:ax-std"]
[dependencies]
ax-std = { workspace = true, optional = true }
[package.metadata.axstd]
features = ["log-level-debug"]
3) src/main.rs
#[cfg(feature = "arceos")]
use ax_std as _;
fn main() {
println!("Hello from myapp!");
}
arceosfeature 由 axbuild 的 std-aware 构建流程注入;应用代码保持普通 Ruststdapp 风格。
4) 验证
cargo xtask arceos qemu --package arceos-myapp --arch aarch64
4.2 使用 axstd 的 std 风格 API
对于复杂应用(如 httpserver),axstd 提供了接近 Rust std 的 API:
use std::{io::Read, net::TcpListener, thread, time::Duration};
fn main() {
let listener = TcpListener::bind("0.0.0.0:8080").unwrap();
loop {
let mut stream = listener.accept().unwrap().0;
let mut buf = [0u8; 1024];
stream.read(&mut buf).ok();
// 处理请求...
thread::sleep(Duration::from_millis(100));
}
}
对应 Cargo.toml 需要通过 arceos feature 为 axbuild 注入网络能力:
[features]
default = []
arceos = ["dep:ax-std", "ax-std/net"]
[dependencies]
ax-std = { workspace = true, optional = true }
4.3 C 应用覆盖
C 应用覆盖由 test-suit/arceos/c 维护;apps/arceos 只保留 Rust std app。
4.4 Feature 与应用对应关系
| 功能需求 | 需要启用的 feature | 示例命令 |
|---|---|---|
| 最小运行 | ax-std | --package arceos-helloworld |
| 多任务 | multitask | 在应用 Cargo.toml 中启用 |
| 网络 | net | --package arceos-httpserver |
| 文件系统 | fs 或 fs-ng | --package arceos-shell |
| 多核 | smp | --arch aarch64 + SMP=4 |
| PCI 设备 | bus-pci | 默认 |
| MMIO 设备 | bus-mmio | --features bus-mmio |
5. 平台开发
5.1 动态平台扩展点
仓库内置平台路径固定为 axplat-dyn。新增板卡或 QEMU 变体时,优先把平台事实接入运行时发现链路:
- somehal:启动入口、FDT/ACPI/UEFI、内存图、CPU、时钟和中断 事实来源。
- axplat-dyn:把 somehal 的运行时事实转成
ax-plat契约,并接入设备探测 glue。 - ax-driver / rdrive:通过 FDT/ACPI/PCI 或外部自定义 probe 注册设备。
外部 ax-plat-* crate 只作为兼容边界存在,不是当前仓库内置维护路径,也不再通过 build feature 或 --platform 在内置构建链中选择。
5.2 平台目录
| 目录 | 内容 |
|---|---|
platforms/ | 工作区内平台契约和动态平台实现;当前内置平台路径为 axplat-dyn |
platforms/axplat-dyn/ | 动态平台加载(UEFI/FDT/ACPI 运行时平台事实与设备探测 glue) |
AArch64、RISC-V QEMU、x86_64 QEMU、LoongArch QEMU 和 SG2002 板卡默认由 axplat-dyn 通过 UEFI/设备树/ACPI 等运行时信息加载。仓库不再内置 SG2002 或其他固定板级平台 crate。
旧的按平台 feature 或 --plat 选择实现的写法需要迁移:直接使用 --arch 选择目标架构。动态路径会进入 axplat-dyn 和 UEFI/FDT/ACPI 启动链路。
5.3 添加板卡支持
- 确认固件表、FDT/ACPI 或 UEFI 能描述必要硬件资源。
- 在
somehal或axplat-dynglue 中补齐运行时事实转译。 - 在
ax-driver/rdrive中补齐对应设备 probe 或外部自定义 probe。 - 验证:
cargo xtask arceos qemu --package arceos-helloworld --arch <arch>
6. 测试
6.1 单元测试
对于支持 std 测试的基础 crate,直接运行:
cargo test -p ax-errno
cargo test -p ax-kspin
6.2 test-suit 集成测试
ArceOS 的集成测试位于 test-suit/arceos/,按功能分类:
| 类别 | 测试项 |
|---|---|
task/ | affinity, ipi, irq, lockdep, parallel, priority, sleep, tls, wait_queue, yield |
net/ | httpclient |
fs/ | shell |
display/ | 显示测试 |
memtest/ | 内存测试 |
exception/ | 异常处理 |
C 测试位于 test-suit/arceos/c/:helloworld, httpclient, memtest, pthread。
6.3 测试配置格式
每个测试由两个 TOML 文件定义:
build-<target>.toml — 构建配置:
features = ["ax-std"]
log = "Warn"
max_cpu_num = 4
[env]
AX_IP = "10.0.2.15"
AX_GW = "10.0.2.2"
qemu-<arch>.toml — QEMU 运行配置:
args = ["-machine", "virt", "-cpu", "cortex-a72", "-m", "128M", "-smp", "4"]
uefi = false
to_bin = true
success_regex = ["All tests passed!"]
fail_regex = ["(?i)\\bpanic(?:ked)?\\b"]
关键字段说明:
| 字段 | 说明 |
|---|---|
features | 启用的 ArceOS feature 列表 |
log | 日志级别(error/warn/info/debug/trace) |
max_cpu_num | 最大 CPU 数 |
args | QEMU 启动参数 |
success_regex | 匹配成功的正则 |
fail_regex | 匹配失败的正则 |
6.4 运行测试
# 通过 xtask 运行 ArceOS 全部 QEMU 测试
cargo xtask arceos test qemu --target riscv64gc-unknown-none-elf
# 指定架构运行
cargo xtask arceos test qemu --target aarch64-unknown-none-softfloat
6.5 添加新测试用例
- 在
test-suit/arceos/rust/<category>/或test-suit/arceos/c/下创建测试项目 - 编写
build-<target>.toml和qemu-<arch>.toml - 确认
success_regex和fail_regex能正确匹配输出 - 通过
cargo xtask arceos test qemu验证