1. 目录搜索上下文(Directory Search Context)
struct yaffsfs_dirsearchcontext
是 YAFFS2 文件系统中用于 目录遍历操作 的核心数据结构,专门管理 readdir()
等目录操作的状态。
结构体定义(典型实现)
c
struct yaffsfs_dirsearchcontext {
struct yaffs_obj *dirObj; // 当前搜索的目录对象
struct list_head *listPtr; // 当前遍历的目录项链表指针
struct yaffs_obj *nextReturn; // 下一个要返回的目录项对象
int offset; // 当前目录偏移量(索引位置)
unsigned magic; // 魔数校验(用于检测内存损坏)
};
2. yaffsfs_dsc[]
数组的作用
功能定位
- 目录遍历状态机:每个元素保存一个独立的目录遍历会话状态
- 支持多任务并发:允许多个任务同时遍历不同目录
- 资源池管理:预分配固定数量的上下文对象,避免动态内存分配
工作流程
User YAFFS2 yaffsfs_dsc[] opendir("/data") 分配空闲上下文 返回 DIR* (指向上下文) readdir(DIR*) 通过 DIR* 找到上下文 从 listPtr 获取下一项 返回 dirent 结构 closedir(DIR*) 释放上下文 User YAFFS2 yaffsfs_dsc[]
3. 关键字段详解
字段 | 类型 | 作用 |
---|---|---|
dirObj |
struct yaffs_obj* |
指向当前遍历的目录对象(如 /data 对应的 YAFFS 对象) |
listPtr |
struct list_head* |
当前遍历位置在目录链表中的指针(YAFFS 用链表组织目录项) |
nextReturn |
struct yaffs_obj* |
缓存的下一个待返回对象(优化性能,避免重复遍历) |
offset |
int |
当前目录项的索引号(对应 telldir() 的返回值) |
magic |
unsigned |
魔数(如 0xDEADBEEF ),用于检测上下文是否被意外覆盖或释放后重用 |
4. 源码中的典型操作
(1) 分配上下文 (yaffsfs_opendir
)
c
DIR *yaffsfs_opendir(const char *dirname) {
// 查找空闲槽位
for(i = 0; i < YAFFSFS_N_DIRSEARCH_CONTEXTS; i++) {
if(yaffsfs_dsc[i].magic != YAFFSFS_DIRSEARCH_MAGIC) {
ctx = &yaffsfs_dsc[i];
break;
}
}
// 初始化上下文
ctx->dirObj = dirObj;
ctx->listPtr = &dirObj->variant.directory_variant.children;
ctx->nextReturn = NULL;
ctx->offset = 0;
ctx->magic = YAFFSFS_DIRSEARCH_MAGIC; // 设置魔数
return (DIR *)ctx;
}
(2) 遍历目录 (yaffsfs_readdir
)
c
struct dirent *yaffsfs_readdir(DIR *dirp) {
struct yaffsfs_dirsearchcontext *ctx = (struct yaffsfs_dirsearchcontext *)dirp;
// 校验魔数(防止非法指针)
if(ctx->magic != YAFFSFS_DIRSEARCH_MAGIC) return NULL;
// 获取下一个目录项
if(ctx->nextReturn) {
obj = ctx->nextReturn;
ctx->nextReturn = NULL;
} else {
list_for_each(pos, ctx->listPtr) {
obj = list_entry(pos, struct yaffs_obj, siblings);
ctx->listPtr = pos->next; // 更新链表指针
break;
}
}
// 填充 dirent 结构
strncpy(dirent->d_name, obj->name, NAME_MAX);
dirent->d_ino = obj->obj_id;
ctx->offset++;
return dirent;
}
(3) 释放上下文 (yaffsfs_closedir
)
c
int yaffsfs_closedir(DIR *dirp) {
struct yaffsfs_dirsearchcontext *ctx = (struct yaffsfs_dirsearchcontext *)dirp;
// 清除魔数(标记为可用)
ctx->magic = 0;
return 0;
}
5. 设计特点与优化
(1) 静态数组 vs 动态分配
方式 | 优点 | 缺点 |
---|---|---|
静态数组 | 无内存碎片,确定性延迟 | 数量固定,可能耗尽 |
动态分配 | 按需分配,无上限限制 | 内存碎片,非实时性 |
YAFFS2 选择静态数组以满足嵌入式实时性要求。
(2) 魔数校验机制
-
内存安全:检测野指针或释放后重用
-
实现方式 :
c#define YAFFSFS_DIRSEARCH_MAGIC 0xDEADBEEF // 使用前校验 if(ctx->magic != YAFFSFS_DIRSEARCH_MAGIC) { yaffs_trace(YAFFS_TRACE_BUG, "Invalid dir context magic!"); return -EBADF; }
(3) 链表遍历优化
nextReturn
字段缓存下一个对象,避免每次readdir()
都遍历链表- 目录项变更时自动失效缓存(通过 YAFFS 对象状态机)
6. 配置参数
在 yaffsfs_config.h
中定义数组大小:
c
#ifndef YAFFSFS_N_DIRSEARCH_CONTEXTS
#define YAFFSFS_N_DIRSEARCH_CONTEXTS 8 // 默认支持8个并发目录遍历
#endif
struct yaffsfs_dirsearchcontext yaffsfs_dsc[YAFFSFS_N_DIRSEARCH_CONTEXTS];
7. 常见问题排查
(1) 目录遍历崩溃
- 可能原因:魔数校验失败(内存越界破坏上下文)
- 解决方案:增加内存检测工具(如 ARM Cortex-M 的 MPU)
(2) opendir 返回 NULL
-
可能原因 :
YAFFSFS_N_DIRSEARCH_CONTEXTS
不足 -
解决方案 :
c// 增加配置 #define YAFFSFS_N_DIRSEARCH_CONTEXTS 16
(3) readdir 顺序异常
-
可能原因:目录项链表被修改(如并发创建/删除文件)
-
解决方案 :对目录对象加锁
cyaffs_lock_dir(ctx->dirObj); // ... 遍历操作 ... yaffs_unlock_dir(ctx->dirObj);
总结
struct yaffsfs_dirsearchcontext yaffsfs_dsc[]
是 YAFFS2 实现高效目录遍历的核心机制:
- 静态资源池:预分配固定数量上下文
- 状态保持:保存目录遍历位置和对象指针
- 安全校验:通过魔数检测内存错误
- 性能优化:链表指针缓存减少遍历开销
这种设计完美契合嵌入式系统对确定性、低内存开销的需求,是 YAFFS2 轻量级文件系统架构的典型体现。