ax-fs
路径:
os/arceos/modules/axfs类型:库 crate 分层:ArceOS 层 / ArceOS 内核模块 版本:0.3.0-preview.3文档依据:Cargo.toml、src/lib.rs、src/root.rs、src/partition.rs、src/dev.rs、src/fops.rs、src/fs/fatfs.rs、src/fs/ext4fs.rs、src/mounts.rs、os/arceos/modules/axruntime/src/lib.rs、os/arceos/api/ax-api/src/imp/fs.rs、os/arceos/api/arceos_posix_api/src/imp/fs.rs
ax-fs 是当前仓库中“旧文件系统栈”的系统装配器。它本身并不是一个具体文件系统实现,而是把块设备访问、分区扫描、FAT/ext4 适配、ramfs/devfs 以及根目录挂载树组合在一起,再向 ArceOS 运行时、ax-api 和 ax-posix-api 暴露一套统一的文件接口。
架构设计
设计定位
ax-fs 位于 ax-runtime 与旧版 axfs_vfs trait 生态之间,承担的是“启动期装配 + 运行期路径路由”双重职责:
- 启动期,它从
ax-driver提供的块设备中取出第一个块设备,解析bootargs中的root=参数,扫描 GPT 或直接把整盘视为单分区,再决定根文件系统应该落在哪个分区上。 - 运行期,它通过
RootDirectory把根文件系统、额外挂载分区以及/proc、/sys这类伪文件树拼成一个统一视图。 - API 层,它提供两套接口:
api模块更接近std::fs风格,fops模块则更像内核内部使用的打开文件/目录对象。
这意味着 ax-fs 的重心不是“实现某种文件系统格式”,而是“把多 种旧栈组件按当前系统启动方式拼起来”。
模块结构
src/lib.rs:初始化主入口。负责选择块设备、解析root=、触发 GPT 扫描与根文件系统初始化。src/dev.rs:把AxBlockDevice包装成带游标的Disk,再切出Partition视图。整个旧栈默认以 512B block 为基本访问粒度。src/partition.rs:解析 GPT 分区表,检测 FAT/ext4 魔数,提取UUID/PARTUUID,并根据检测结果创建具体文件系统实例。src/root.rs:定义RootDirectory、挂载点表、全局当前目录,以及lookup/create/remove/rename等根级路径路由逻辑。src/fs/fatfs.rs:把axfatfs适配为ax_fs_vfs::VfsOps/VfsNodeOps。src/fs/ext4fs.rs:把rsext4适配为ax_fs_vfs::VfsOps/VfsNodeOps。src/fs/mod.rs:暴露旧栈下的具体文件系统实现,并直接复用axfs_devfs、axfs_ramfs。src/mounts.rs:创建基于ramfs的/proc、/sys伪目录树。src/fops.rs:定义File、Directory、OpenOptions,并使用ax_cap_access::WithCap在打开后绑定读写执行能力。src/api/*:向上提供更接近用户态或通用库风格的辅助函数。
1.3 启动与挂载主线
ax-runtime 在启用 fs feature 后会调用 ax_fs::init_filesystems(),实际主线如下:
几个实现细节尤其重要:
root=支持/dev/sdaX、/dev/mmcblkXpY、PARTUUID=、UUID=、PARTLABEL=五类选择方式。- 如果 GPT 解析失败或没有识别到支持的文件系统,
ax-fs会记录告警;最终如果没有可用根文件系统,则回退到ramfs。 - 非根分区会被自动挂到
/boot或/<partition.name>;其中名字包含boot的分区优先挂到/boot。 /proc与/sys不是独立的动态内核文件系统,而是启动时填充好的ramfs树。
1.4 与相邻 crate 的边界
ax-fs是聚合层,不是叶子文件系统。真正的叶子实现是axfs_ramfs、axfs_devfs、axfatfs适配层以及rsext4适配层。ax-fs自己维护挂载点表和根目录拼接逻辑;axfs_vfs并不提供挂载图管理能力。ax-fs的当前工作目录是ROOT_DIR/CURRENT_DIR这组全局静态对象,而不是任务局部对象。 这一点与ax-fs-ng的FS_CONTEXT有本质差异。root.rs顶部已经明确写出 TODO:当挂载点存在包含关系时,这套路由逻辑并不“工作得很好”。因此它更适合简单的根目录拼装,而不是复杂命名空间系统。
核心功能
功能概览
- 启动时自动选择根文件系统,并在 FAT 与 ext4 间做格式检测。
- 提供 GPT 分区扫描与
UUID/PARTUUID识别。 - 把主根文件系统、额外挂载分区和伪文件系统合并成统一根目录。
- 通过
fops提供打开文件、打开目录、读写、截断、遍历、重命名等低层接口。 - 通过
api提供read、write、create_dir、current_dir等高层辅助函数。
2.2 关键实现细节
根目录拼接
RootDirectory 持有一个 main_fs 和一组 mounts。对 lookup、create、remove 这类路径操作,它会先选取“最长前缀命中的挂载点”,再把剩余路径转发给具体文件系统;对 read_dir,它会把挂载点名和主根目录条目合并后去重输出。
权限模型
fops::File/Directory 打开时会根据 OpenOptions 生成 Cap,并与 VfsNodeAttr::perm() 进行比对。也就是说,旧栈里的权限控制更接近“打开时绑定能力”,而不是完整的 Unix uid/gid/mode 模型。
ext4/FAT 接入方式
- FAT 路径通过
PartitionWrapper把分区包装成axfatfs所需的Read/Write/Seek设备,再适配到VfsNodeOps。 - ext4 路径通过
Jbd2Dev<Disk|Partition>挂载rsext4,由Ext4FileSystem{,Partition}包装成旧VfsOps。
伪文件系统内容
mounts.rs 当前仅创建了少量兼容性节点,例如:
/proc/sys/net/core/somaxconn/proc/sys/vm/overcommit_memory/proc/self/stat/sys/kernel/mm/transparent_hugepage/enabled/sys/devices/system/clocksource/clocksource0/current_clocksource
这些节点本质上是预填充值文件,不具备真正的动态内核视图能力。
2.3 真实限制与注意事项
- 只取第一个块设备,不做多块设备选择策略。
Directory::rename()注释已明确说明:仅在源和目标位于同一已挂载文件系统时才可靠。remove_dir()会显式阻止删除挂载点目录。/proc、/sys目前不是真正的 procfs/sysfs,而是兼容性占位实现。
依赖关系
直接依赖
ax-driver:提供块设备来源。axfs_vfs:旧栈统一 trait 契约。axfs_ramfs、axfs_devfs:旧栈中的内存文件系统与设备文件系统。axfatfs、rsext4:分别承担 FAT 与 ext4 的实际格式实现。ax-cap-access:为fops提供打开后能力控制。