ax-alloc 技术文档
路径:
os/arceos/modules/axalloc类型:库 crate 分层:ArceOS 层 / 内存分配运行时基础件 版本:0.3.0-preview.3文档依据:Cargo.toml、README.md、src/lib.rs、src/default_impl.rs、src/axvisor_impl.rs、src/page.rs、src/tracking.rs
ax-alloc 是 ArceOS 的全局分配入口。它把 ax-allocator 提供的字节分配器和页分配器包装成可直接挂到 #[global_allocator] 的 GlobalAllocator,并额外提供页级接口、使用量统计和可选的分配跟踪能力。它属于运行时叶子基础件:负责“分配”,但不负责页表建立、地址空间管理或物理内存发现,这些职责分别由 ax-mm、ax-hal 和 ax-runtime 承担。
1. 架构设计分析
1.1 设计定位
ax-alloc 在启动链和运行期之间扮演的是“统一分配服务”角色:
- 向下,它复用
ax-allocator或buddy-slab-allocator,而不是自行实现完整分配算法。 - 向上,它向
ax-runtime、ax-mm、ax-hal::paging、ax-driver、ax-dma、ax-api等模块暴露统一的堆/页分配接口。 - 横向,它通过
UsageKind/Usages给页表、DMA、页缓存等不同用途打标签,方便上层做统计与诊断。
因此,ax-alloc 不是“内存管理本体”,而是“内存分配入口”。把它写成虚拟内存系统、页表系统或用户地址空间管理器,都会高估它的职责。
1.2 内部模块划分
src/lib.rs:顶层 feature 分流与公共类型定义。声明UsageKind、Usages,并在默认实现与hv实现之间切换。src/default_impl.rs:默认 ArceOS 路径。把字节分配器与位图页分配器组合成全局分配器。src/axvisor_impl.rs:虚拟化路径。改用buddy-slab-allocator,并支持地址翻译器与 DMA32 页分配。src/page.rs:GlobalPageRAII 封装,负责简单的连续页所有权管理。src/tracking.rs:可选分配跟踪状态,记录Layout、Backtrace和分配代次。
1.3 关键对象
GlobalAllocator:真正实现core::alloc::GlobalAlloc的核心对象。DefaultByteAllocator:由tlsf/slab/buddyfeature 选择的字节分配器别名。BitmapPageAllocator<PAGE_SIZE>:默认路径的页级后端。UsageKind:把内存使用划分为RustHeap、VirtMem、PageCache、PageTable、Dma、Global。Usages:各类用途的累计统计。GlobalPage:页块 RAII 包装,只负责申请/释放连续页,不负责映射属性。AllocationInfo:只在tracking下存在的诊断元数据。
1.4 默认实现主线
默认路径采用“字节分配器 + 页分配器”的两级设计:
实现里的关键约束有:
global_init()只负责建立第一段可分配区域;后续热插入或额外区域接入走global_add_memory()。- 默认两级模式下,
alloc()会根据当前堆大小和申请大小动态决定扩堆块大小,再从页分配器取页补给字节分配器。 level-1feature 会退化为单级字节分配器,此时alloc_pages_at()明确unimplemented!()。- 对
UsageKind::RustHeap的统计有特判,避免“扩堆用页”和“堆内字节分配”重复记账。
1.5 hv 与 tracking 分支
hv:忽略ax-allocator的算法 feature,转而使用buddy-slab-allocator。global_init()需要额外注入AddrTranslator,并暴露alloc_dma32_pages()。当前这一路径的used_bytes()、available_bytes()、used_pages()、available_pages()都返回0,因为底层库没有提供对应统计。tracking:在GlobalAlloc::alloc/dealloc外围维护一个全局分配表,并记录axbacktrace::Backtrace。tracking::with_state()用每 CPU 的IN_GLOBAL_ALLOCATOR标记避免跟踪逻辑再次触发分配而递归爆栈。
2. 核心功能说明
2.1 主要功能
- 为系统提供可挂到
#[global_allocator]的全局堆分配器。 - 提供页级接口
alloc_pages()/alloc_pages_at()/dealloc_pages()。 - 提供
GlobalPage这一轻量页所有权对象。 - 提供按用途分类的使用量统计,以及可选的 backtrace 跟踪。
2.2 关键 API 与真实使用位置
global_init()/global_add_memory():由ax-runtime/src/lib.rs的init_allocator()调用,是 ArceOS 启动期接入堆的入口。global_allocator().alloc_pages():被ax-mm/src/backend/alloc.rs、ax-hal/src/paging.rs等页级消费者直接使用。global_allocator().alloc()/dealloc():被ax-api/src/imp/mem.rs直接转发给更上层 API。GlobalPage::alloc*():适合需要“拿到一段连续页并在 drop 时自动归还”的简单路径。
2.3 使用边界
ax-alloc不负责扫描物理内存,也不决定哪些区域可以加到堆里;这些输入由ax-runtime和ax-hal提供。ax-alloc不负责地址映射策略;页表和地址空间对象依然在ax-mm层。Usages是统计视图,不是安全边界或配额系统。