xt-sdk 文档 v1.0.3
xt-sdk 嵌入式 SDK API 参考
载入中...
搜索中...
未找到
xt_vfs - 虚拟文件系统模块

版本:0.1 | 日期:2026-06-16 | 路径:components/xt_core/components/xt_vfs.h/.c

子文档:


一、概述

xt_vfs 是一个面向嵌入式系统的虚拟文件系统框架,支持多后端挂载、两级线程安全锁、三种内存模式。在 xt_fs 基础上重构——从单后端全局函数升级为多后端可插拔架构。

特性 xt_fs xt_vfs
后端模型 单后端,平台层硬对接 多后端,ops 接口可插拔
API 数量 28 个 35 个
线程安全 平台层自管 Core 内置两级锁,宏可关
内存策略 平台层 malloc 动态/外部/静态三模式
句柄安全 整数 fd generation 编码防悬空
路径路由 直通 挂载点最长前缀匹配 + 相对路径解析
目录可裁剪 否 XT_VFS_ENABLE_DIR 宏

1.1 设计原则

  • **全局单例**:调用者无需传入 VFS 句柄,所有 API 直接调用
  • **最小核心**:后端只需实现 9 个函数(open/close/read/write/seek/tell/fsync/mount/unmount)即可工作
  • **锁分离**:VFS 全局锁保护元数据,后端锁保护 I/O,不同后端完全并行
  • **内存可控**:编译期选择动态/外部/静态,零分配裸机可运行

1.2 依赖

依赖 用途
xt_list.h 双向循环链表:空闲链表 + 挂载表
CMSIS-OS2(可选) mutex 锁 + 线程 ID
xt_malloc.h(可选) 堆内存分配
xt_log.h XT_ASSERT_MSG 断言

二、核心概念

2.1 挂载点与路径路由

文件系统通过 prefix(如 /flash、/sd)挂载到 VFS。路径操作时 Core 按**最长前缀匹配**找到对应后端,将剩余子路径传给后端。

挂载 /flash → LittleFS → /flash/log.txt → subpath = "log.txt"
挂载 /flash1 → FatFS → /flash1/data.bin → subpath = "data.bin"
挂载 /sd → native → /sd/photo.jpg → subpath = "photo.jpg"

**嵌套挂载**:/c 用 native,/c/mnt/ram 用 ramfs。/c/mnt/ram/file.txt 匹配 /c/mnt/ram(最长前缀优先)。

2.2 句柄与 generation

文件句柄 xt_vfs_fd_t 编码为 (generation << 16) | (table_index)。每次分配 generation++(从 1 开始),close 后旧 fd 因 generation 不匹配被拒绝。XT_VFS_INVALID_FD 固定为 (xt_vfs_fd_t)(-1)。

目录句柄 xt_vfs_dir_t 为 opaque 指针,内部通过 dd_vfs_idx + dd_rsv 编码 generation。

2.3 两级锁

锁 保护 持有时机
VFS 全局锁 挂载表、句柄表、线程上下文表 查表/分配/释放时短暂持有
后端锁(每挂载点独立) 该后端所有 I/O 操作 ops 调用期间持有

锁顺序永远是先全局锁→再后端锁,不允许反向。

2.4 线程 errno

xt_vfs_errno() 通过 osThreadGetId() 查 thread_table 返回当前线程的错误码。裸机模式(XT_VFS_ENABLE_THREAD_SAFE=0)固定用槽 0。

2.5 CWD 相对路径

#if XT_VFS_ENABLE_CWD 启用。xt_vfs_chdir 设置当前线程工作目录,后续操作可用相对路径(不以 / 开头)。支持 . 和 .. 规范化。


三、数据结构

3.1 公开类型

typedef int32_t xt_vfs_err_t; // 错误码,详细列表见 XT_VFS_ERR_* 宏
typedef int32_t xt_vfs_fd_t; // 文件描述符,内部编码 generation+index
typedef uint32_t xt_vfs_size_t; // 大小(无符号)
typedef int32_t xt_vfs_ssize_t; // 有符号大小(read/write/seek/tell 返回值)
typedef uint32_t xt_vfs_mode_t; // 打开标志/权限位
typedef uint32_t xt_vfs_time_t; // 时间
typedef int32_t xt_vfs_off_t; // 偏移量
typedef int32_t xt_vfs_whence_t; // seek 寻址基准(XT_VFS_SEEK_SET=0/CUR=1/END=2)
typedef int32_t xt_vfs_ino_t; // inode 号
int32_t xt_vfs_whence_t
寻址基准类型
int32_t xt_vfs_fd_t
文件描述符类型,内部编码 generation+index,由 VFS Core 生成,用户不应自行构造
uint32_t xt_vfs_mode_t
文件模式类型(权限 + 类型)
int32_t xt_vfs_off_t
偏移量类型
int32_t xt_vfs_err_t
错误码类型,详细错误码见 XT_VFS_ERR_* 系列宏
uint32_t xt_vfs_time_t
时间类型(固定 32 位)
int32_t xt_vfs_ino_t
inode 编号类型
uint32_t xt_vfs_size_t
文件大小类型(无符号)
int32_t xt_vfs_ssize_t
文件大小类型(有符号)

3.2 公开结构体

xt_vfs_stat_t // st_size, st_mode, st_atime, st_mtime, st_ctime
xt_vfs_statfs_t // f_blocks, f_bfree, f_bsize, f_files, f_ffree(类型 xt_vfs_size_t)
xt_vfs_utimbuf_t // actime, modtime
xt_vfs_dir_t // opaque,仅指针使用
xt_vfs_dirent_t // d_ino, d_type, d_name[XT_VFS_FILENAME_MAX]
xt_vfs_config_t // max_mounts/files/dirs/threads + 外部内存指针
struct xt_vfs_stat xt_vfs_stat_t
文件状态信息
struct xt_vfs_dirent xt_vfs_dirent_t
目录项信息
struct xt_vfs_dir xt_vfs_dir_t
目录句柄(opaque,内部字段不暴露)
struct xt_vfs_statfs xt_vfs_statfs_t
文件系统状态信息
struct xt_vfs_utimbuf xt_vfs_utimbuf_t
文件时间信息
struct xt_vfs_config xt_vfs_config_t
VFS 初始化配置

3.3 后端 ops 接口(xt_vfs_ops_t,26 个函数指针,const)

层级 函数 标注
**最小子集**(必须实现) mount, unmount, open, close, read, write, seek, tell, fsync @note 最小对接子集,所有后端必须实现
常用推荐 remove, rename, stat, fstat, statfs @note 常用推荐接口
可选 truncate, ftruncate, access, utime, sync_all, mkdir, rmdir, opendir, closedir, readdir, telldir, seekdir @note 可选接口,置 NULL 则返回 XT_VFS_ERR_NOSYS

**ops 都是 const**:

static const xt_vfs_ops_t s_ramfs_ops = {
.mount = ramfs_mount,
.unmount = ramfs_unmount,
.open = ramfs_open,
// ...
};
xt_vfs_mount("/ram", &s_ramfs_ops, ctx);
struct xt_vfs_ops xt_vfs_ops_t
后端操作接口(前向声明)
xt_vfs_err_t xt_vfs_mount(const char *path, const xt_vfs_ops_t *ops, void *ctx)
挂载后端文件系统

四、API 参考

以下为函数签名大纲,完整的参数说明、返回值、注意事项请查看 xt_vfs(虚拟文件系统) 。

4.1 生命周期

函数签名 说明
xt_vfs_err_t xt_vfs_init(const xt_vfs_config_t *config) 初始化 VFS 实例
xt_vfs_err_t xt_vfs_deinit(void) 销毁 VFS 实例

4.2 挂载管理

函数签名 说明
xt_vfs_err_t xt_vfs_mount(const char *path, const xt_vfs_ops_t *ops, void *ctx) 挂载后端文件系统
xt_vfs_err_t xt_vfs_unmount(const char *path) 卸载后端文件系统

4.3 文件读写

函数签名 说明
xt_vfs_fd_t xt_vfs_open(const char *path, xt_vfs_mode_t flags) 打开文件
xt_vfs_err_t xt_vfs_close(xt_vfs_fd_t fd) 关闭文件
xt_vfs_ssize_t xt_vfs_read(xt_vfs_fd_t fd, void *buf, xt_vfs_size_t size) 读取文件
xt_vfs_ssize_t xt_vfs_write(xt_vfs_fd_t fd, const void *buf, xt_vfs_size_t size) 写入文件
xt_vfs_ssize_t xt_vfs_seek(xt_vfs_fd_t fd, xt_vfs_off_t offset, xt_vfs_whence_t whence) 文件定位
xt_vfs_ssize_t xt_vfs_tell(xt_vfs_fd_t fd) 获取当前文件位置
xt_vfs_err_t xt_vfs_fsync(xt_vfs_fd_t fd) 同步单个文件到存储设备

4.4 文件信息与管理

函数签名 说明
xt_vfs_err_t xt_vfs_remove(const char *path) 删除文件
xt_vfs_err_t xt_vfs_rename(const char *old_path, const char *new_path) 重命名文件
xt_vfs_err_t xt_vfs_stat(const char *path, xt_vfs_stat_t *stat) 获取文件状态
xt_vfs_err_t xt_vfs_fstat(xt_vfs_fd_t fd, xt_vfs_stat_t *stat) 获取已打开文件的状态
xt_vfs_err_t xt_vfs_statfs(const char *path, xt_vfs_statfs_t *statfs) 获取文件系统状态
xt_vfs_err_t xt_vfs_truncate(const char *path, xt_vfs_off_t length) 截断文件到指定大小
xt_vfs_err_t xt_vfs_ftruncate(xt_vfs_fd_t fd, xt_vfs_off_t length) 截断已打开的文件
xt_vfs_err_t xt_vfs_access(const char *path, xt_vfs_mode_t amode) 检查文件访问权限
xt_vfs_err_t xt_vfs_utime(const char *path, const xt_vfs_utimbuf_t *buf) 更新文件时间
xt_vfs_err_t xt_vfs_sync_all(const char *path) 同步所有文件到存储设备

4.5 目录操作

函数签名 说明
xt_vfs_err_t xt_vfs_mkdir(const char *path) 创建目录
xt_vfs_err_t xt_vfs_rmdir(const char *path) 删除空目录
xt_vfs_dir_t *xt_vfs_opendir(const char *path) 打开目录
xt_vfs_err_t xt_vfs_closedir(xt_vfs_dir_t *dir) 关闭目录
xt_vfs_dirent_t *xt_vfs_readdir(xt_vfs_dir_t *dir) 读取目录项
xt_vfs_err_t xt_vfs_rewinddir(xt_vfs_dir_t *dir) 重置目录读取位置
xt_vfs_off_t xt_vfs_telldir(xt_vfs_dir_t *dir) 获取目录读取位置
xt_vfs_err_t xt_vfs_seekdir(xt_vfs_dir_t *dir, xt_vfs_off_t loc) 设置目录读取位置

4.6 工作目录

函数签名 说明
xt_vfs_err_t xt_vfs_chdir(const char *path) 切换当前工作目录
char *xt_vfs_getcwd(char *buf, xt_vfs_size_t size) 获取当前工作目录

4.7 错误与状态

函数签名 说明
xt_vfs_err_t xt_vfs_errno(void) 获取当前线程的最后一个错误码
const char *xt_vfs_strerror(xt_vfs_err_t err) 获取错误码对应的字符串描述
bool xt_vfs_is_active(void) 检查 VFS 实例是否已激活

五、编译配置

所有宏在 xt_vfs_port.h 中定义,采用 #if !defined() 模式,xmake 可覆盖。

宏 默认值 说明
XT_VFS_ENABLE_THREAD_SAFE 1 线程安全(CMSIS-OS2 mutex)
XT_VFS_USE_HEAP 1 堆内存(xt_malloc)
XT_VFS_ENABLE_CWD 0 相对路径(chdir/getcwd)
XT_VFS_ENABLE_DIR 1 目录操作
XT_VFS_ENABLE_STATIC_TEST 0 静态测试模式
XT_VFS_PATH_MAX 128 最大路径长度
XT_VFS_FILENAME_MAX 64 最大文件名长度
XT_VFS_MOUNT_PREFIX_MAX 16 挂载前缀最大长度
XT_VFS_MAX_MOUNTS 4 最大挂载点数(静态模式)
XT_VFS_MAX_FILES 8 最大打开文件数(静态模式)
XT_VFS_MAX_DIRS 4 最大打开目录数(静态模式)
XT_VFS_MAX_THREADS 8 最大线程上下文槽数

xmake 传递示例 (xt_core/xmake.lua):

option("xt_vfs_path_max")
set_default("128")
set_description("Max path length")
option_end()
target("xt_core")
add_options("xt_vfs_path_max")
if get_config("xt_vfs_path_max") then
add_defines("XT_VFS_PATH_MAX=" .. get_config("xt_vfs_path_max"), {public = true})
end

裸机最小配置 (无堆+无锁+无目录):

XT_VFS_USE_HEAP=0 XT_VFS_ENABLE_THREAD_SAFE=0 XT_VFS_ENABLE_DIR=0

RAM 占用约 900 字节(静态数组全在 BSS 段)。


六、常见模式

6.1 基本文件操作

// 初始化 + 挂载
xt_vfs_config_t cfg = { .max_mounts = 2, .max_files = 8, .max_dirs = 4, .max_threads = 4 };
xt_vfs_mount("/flash", &littlefs_ops, &lfs_ctx);
// 写文件
if (fd != XT_VFS_INVALID_FD) {
xt_vfs_write(fd, "hello", 5);
}
// 读文件
fd = xt_vfs_open("/flash/data.bin", XT_VFS_O_RDONLY);
char buf[32] = {0};
xt_vfs_read(fd, buf, sizeof(buf));
// 清理
#define XT_VFS_O_RDONLY
只读
xt_vfs_ssize_t xt_vfs_read(xt_vfs_fd_t fd, void *buf, xt_vfs_size_t size)
读取文件
xt_vfs_err_t xt_vfs_init(const xt_vfs_config_t *config)
初始化 VFS 实例
#define XT_VFS_O_TRUNC
截断,文件存在且可写时清空内容
xt_vfs_ssize_t xt_vfs_write(xt_vfs_fd_t fd, const void *buf, xt_vfs_size_t size)
写入文件
#define XT_VFS_O_CREAT
创建,不存在时创建
#define XT_VFS_INVALID_FD
无效文件描述符
xt_vfs_err_t xt_vfs_deinit(void)
销毁 VFS 实例
xt_vfs_err_t xt_vfs_close(xt_vfs_fd_t fd)
关闭文件
#define XT_VFS_O_RDWR
读写
xt_vfs_fd_t xt_vfs_open(const char *path, xt_vfs_mode_t flags)
打开文件

6.2 多后端挂载

xt_vfs_mount("/flash", &littlefs_ops, &lfs_ctx); // flash 上的 LittleFS
xt_vfs_mount("/sd", &fatfs_ops, &fat_ctx); // SD 卡上的 FatFS
xt_vfs_mount("/ram", &ramfs_ops, &ram_ctx); // 内存文件系统
// 三者完全隔离,同时操作互不影响
xt_vfs_fd_t f1 = xt_vfs_open("/flash/log.txt", ...);
xt_vfs_fd_t f2 = xt_vfs_open("/sd/photo.jpg", ...);
xt_vfs_fd_t f3 = xt_vfs_open("/ram/temp.bin", ...);

6.3 实现最小后端(只读 ROMFS)

只需实现 9 个最小子集函数,其余置 NULL:

static const xt_vfs_ops_t s_romfs_ops = {
.mount = NULL, // ROMFS 无需初始化
.unmount = NULL,
.open = romfs_open, // 只读打开
.close = romfs_close,
.read = romfs_read,
.write = NULL, // 只读,置 NULL → 返回 NOSYS
.seek = romfs_seek,
.tell = romfs_tell,
.fsync = NULL, // 只读无需同步
// 其余全部 NULL
};

6.4 错误处理模式

xt_vfs_fd_t fd = xt_vfs_open("/flash/file.txt", XT_VFS_O_RDONLY);
if (fd == XT_VFS_INVALID_FD) {
xt_printf("open failed: %s (err=%d)\n", xt_vfs_strerror(err), (int)err);
return;
}
xt_vfs_ssize_t n = xt_vfs_read(fd, buf, size);
if (n < 0) {
xt_printf("read failed: %s\n", xt_vfs_strerror(xt_vfs_errno()));
return;
}
int xt_printf(const char *fmt,...)
格式化输出
const char * xt_vfs_strerror(xt_vfs_err_t err)
获取错误码对应的字符串描述
xt_vfs_err_t xt_vfs_errno(void)
获取当前线程的最后一个错误码

6.5 静态内存模式(裸机无堆)

// 编译时 XT_VFS_USE_HEAP=0,不传 mem 字段
.max_mounts = XT_VFS_MAX_MOUNTS, // 使用宏
.max_files = XT_VFS_MAX_FILES,
.max_dirs = XT_VFS_MAX_DIRS,
.max_threads = XT_VFS_MAX_THREADS,
.mount_mem = NULL, // 不传外部内存,用内部 static 数组
};
#define XT_VFS_MAX_FILES
最大同时打开文件数(静态模式)
#define XT_VFS_MAX_THREADS
最大线程上下文槽位数
#define XT_VFS_MAX_MOUNTS
最大挂载点数(静态模式)
#define XT_VFS_MAX_DIRS
最大同时打开目录数(静态模式)

6.6 外部内存模式

static xt_vfs_mount_t my_mount_table[4];
static xt_vfs_handle_t my_file_table[16];
static xt_vfs_handle_t my_dir_table[8];
static xt_vfs_thread_ctx_t my_thread_table[4];
.max_mounts = 4, .max_files = 16,
.max_dirs = 8, .max_threads = 4,
.mount_mem = my_mount_table, .mount_mem_size = sizeof(my_mount_table),
.file_mem = my_file_table, .file_mem_size = sizeof(my_file_table),
.dir_mem = my_dir_table, .dir_mem_size = sizeof(my_dir_table),
.thread_mem = my_thread_table, .thread_mem_size = sizeof(my_thread_table),
};
struct xt_vfs_thread_ctx xt_vfs_thread_ctx_t
线程上下文——存储每线程 errno 和可选 CWD

七、反模式

反模式 问题 正确做法
回调中操作同一挂载点 mount 锁非递归,回调中调 open 同 mount 点死锁 回调仅做轻量操作,不调 VFS API
对 static 定时器调 delete 释放栈/全局内存 ng 静态对象不调 delete
close 后用旧 fd generation 校验拒绝 close 后置 XT_VFS_INVALID_FD
挂载点不以 / 开头 路由失败 prefix 必须以 / 开头
rename 跨后端 返回错误 rename 仅在同挂载点内使用
主循环中忘记调 fsync 数据丢失风险 写操作后及时 fsync
静态模式 max_* > 实际数组大小 越界 HardFault init 时校验通过才返回 OK

八、后端移植指南

8.1 最小移植

实现这 9 个函数即可让文件系统后端工作:

xt_vfs_err_t (*mount )(void *ctx); // 挂载,NULL 表示无需初始化
xt_vfs_err_t (*unmount)(void *ctx); // 卸载,NULL 表示无需清理
xt_vfs_err_t (*open )(void *ctx, const char *path, xt_vfs_mode_t flags, void **fh);
xt_vfs_err_t (*close )(void *ctx, void *fh);
xt_vfs_ssize_t (*read )(void *ctx, void *fh, void *buf, xt_vfs_size_t size);
xt_vfs_ssize_t (*write )(void *ctx, void *fh, const void *buf, xt_vfs_size_t size);
xt_vfs_ssize_t (*seek )(void *ctx, void *fh, xt_vfs_off_t offset, xt_vfs_whence_t whence);
xt_vfs_ssize_t (*tell )(void *ctx, void *fh);
xt_vfs_err_t (*fsync )(void *ctx, void *fh); // 同步到存储

**关键约定**:

  • ctx 是挂载时传入的后端私有上下文(如 &lfs 是 LittleFS 实例指针)
  • path 是挂载点下的子路径(如挂载 /flash 后传入 "log.txt")
  • fh 是后端私有文件句柄(如 lfs_file_t *),通过 void **fh 输出
  • 所有错误返回 XT_VFS_ERR_* 系列错误码
  • 可选接口置 NULL,Core 自动返回 XT_VFS_ERR_NOSYS

8.2 LittleFS 对接示例

static xt_vfs_err_t lfs_mount(void *ctx) {
lfs_t *lfs = (lfs_t *)ctx;
return (lfs_mount(lfs, &my_cfg) == LFS_ERR_OK) ? XT_VFS_ERR_OK : XT_VFS_ERR_IO;
}
static xt_vfs_err_t lfs_open(void *ctx, const char *path, xt_vfs_mode_t flags, void **fh) {
lfs_t *lfs = (lfs_t *)ctx;
lfs_file_t *file = malloc(sizeof(lfs_file_t));
int lfs_flags = (flags & XT_VFS_O_RDWR) ? LFS_O_RDWR : (flags & XT_VFS_O_WRONLY) ? LFS_O_WRONLY : LFS_O_RDONLY;
if (flags & XT_VFS_O_CREAT) lfs_flags |= LFS_O_CREAT;
int ret = lfs_file_open(lfs, file, path, lfs_flags);
if (ret < 0) { free(file); return XT_VFS_ERR_IO; }
*fh = file;
return XT_VFS_ERR_OK;
}
static const xt_vfs_ops_t s_lfs_ops = {
.mount = lfs_mount,
.open = lfs_open,
// ... 其他函数类似
};
#define XT_VFS_ERR_IO
IO 错误
#define XT_VFS_O_WRONLY
只写
#define XT_VFS_ERR_OK
成功

8.3 注意事项

  • 后端函数在**后端锁保护**下执行,无需内部加锁
  • 同一后端的 read/write/seek 等可以共用 fh 指针作为索引
  • 错误码必须使用 XT_VFS_ERR_*,不能返回自定义值
  • ops->readdir 返回的 xt_vfs_dirent_t* 指针仅在下一次 readdir 或 closedir 前有效
  • 不要求线程安全(Core 已通过后端锁串行化同一挂载点操作)

九、测试

测试套件位于 tests/xt_vfs/。

cd tests/xt_vfs
xt --target windows/simulator fullclean build
xt --target windows/simulator run

多配置自动化测试:

python run_tests.py # 7 组配置