FATFS学习(2.2):ffconf.h

一:/* Object ID and allocation information (FFOBJID) */

cpp 复制代码
typedef struct {
	FATFS*	fs;				/* Pointer to the hosting volume of this object */
	WORD	id;				/* Hosting volume's mount ID */
	BYTE	attr;			/* Object attribute */
	BYTE	stat;			/* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
	DWORD	sclust;			/* Object data start cluster (0:no cluster or root directory) */
	FSIZE_t	objsize;		/* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
	DWORD	n_cont;			/* Size of first fragment - 1 (valid when stat == 3) */
	DWORD	n_frag;			/* Size of last fragment needs to be written to FAT (valid when not zero) */
	DWORD	c_scl;			/* Containing directory start cluster (valid when sclust != 0) */
	DWORD	c_size;			/* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
	DWORD	c_ofs;			/* Offset in the containing directory (valid when file object and sclust != 0) */
#endif
#if FF_FS_LOCK
	UINT	lockid;			/* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} FFOBJID;

FFOBJID 结构体分析总结

FFOBJID 是 FatFs 库中用于管理文件或目录对象的元数据结构体,记录对象在文件系统中的存储位置、状态、属性及并发控制信息。其成员变量根据配置选项(如 FF_FS_EXFATFF_FS_LOCK)动态扩展,支持不同文件系统特性和功能。


核心成员变量解析
成员变量 类型 说明
fs FATFS* 所属卷指针:指向对象所在的文件系统卷(如 SD 卡、Flash 分区)。
id WORD 卷挂载 ID:标识卷的挂载状态,用于检测卷是否被重新挂载(避免缓存失效)。
attr BYTE 对象属性 :存储 FAT 文件属性(如只读 AM_RDO、隐藏 AM_HID 等)。
stat BYTE 对象链状态 : - b1-b0 : 簇链连续性(0=非连续,2=连续,3=当前会话碎片化)。 - b2: 子目录是否被扩展(如添加新条目导致目录簇链增长)。
sclust DWORD 起始簇号:对象数据的第一个簇号(0 表示空文件或根目录)。
objsize FSIZE_t 对象大小 :文件或目录的实际大小(单位:字节,仅当 sclust ≠ 0 时有效)。

条件编译扩展成员
  1. FF_FS_EXFAT(exFAT 文件系统支持)

    成员变量 类型 说明
    n_cont DWORD 首个片段大小 -1 :当 stat = 3 时有效,记录 exFAT 文件的碎片信息。
    n_frag DWORD 待写入 FAT 的末片段大小:非零时需更新 FAT 表。
    c_scl DWORD 所属目录起始簇 :对象所在的父目录起始簇(仅当 sclust ≠ 0 时有效)。
    c_size DWORD 目录大小与状态 : - b31-b8 : 父目录大小(字节)。 - b7-b0: 目录簇链状态。
    c_ofs DWORD 在父目录中的偏移 :文件对象在目录中的位置(仅当 sclust ≠ 0 时有效)。
  2. FF_FS_LOCK(文件锁支持)

    成员变量 类型 说明
    lockid UINT 文件锁 ID:从 1 开始,用于标识文件锁表中的条目,管理多线程/进程并发访问。

功能与应用场景

  1. 文件/目录操作跟踪

    • sclustobjsize:定位文件数据簇链的起始位置和大小,支持读写操作。

    • stat :优化簇链遍历,连续簇(stat=2)可快速寻址,碎片化簇(stat=3)需动态处理。

  2. exFAT 特性支持

    • n_contn_frag:管理 exFAT 文件的碎片,提升大文件存储效率。

    • c_sclc_ofs:快速定位文件在父目录中的元数据,加速目录遍历。

  3. 并发控制

    • lockid:通过信号量机制防止多线程同时修改同一文件,确保数据一致性。
  4. 卷状态管理

    • id:检测卷是否被卸载后重新挂载,避免使用过时的缓存数据。

配置选项影响

配置宏 影响成员变量 功能扩展说明
FF_FS_EXFAT n_cont, n_frag, c_scl 支持 exFAT 文件系统的碎片管理和目录操作。
FF_FS_LOCK lockid 启用文件锁功能,防止并发冲突。
FF_FS_READONLY (间接影响) 只读模式下无需更新 n_frag 或簇链状态。

典型使用流程

  1. 打开文件

    cpp 复制代码
    FIL fil;
    f_open(&fil, "file.txt", FA_READ);
    // FFOBJID 被初始化,记录 fil 的 sclust、objsize 等
  2. 读取数据

    cpp 复制代码
    UINT br;
    f_read(&fil, buffer, sizeof(buffer), &br);
    // 根据 sclust 和簇链定位数据扇区
  3. 写入数据(exFAT 碎片处理)

    cpp 复制代码
    f_write(&fil, data, size, &bw);
    // 若文件扩展导致碎片,更新 n_cont 和 n_frag
  4. 文件锁控制

    cpp 复制代码
    // 多线程环境中,通过 lockid 加锁
  5. 关闭文件

    cpp 复制代码
    f_close(&fil);
    // 释放 lockid,更新 stat 和 FAT 表(若数据修改)

总结

  • FFOBJID 是 FatFs 管理文件/目录的核心元数据容器,涵盖存储位置、状态、并发控制等。

  • 条件编译成员 扩展了对 exFAT 和文件锁的支持,适应不同文件系统特性和应用场景。

  • 状态位(stat 优化簇链操作,区分连续与碎片化存储,提升读写效率。

  • 多卷与并发 通过 idlockid 确保数据一致性和线程安全。

二:/* File object structure (FIL) */

cpp 复制代码
typedef struct {
	FFOBJID	obj;			/* Object identifier (must be the 1st member to detect invalid object pointer) */
	BYTE	flag;			/* File status flags */
	BYTE	err;			/* Abort flag (error code) */
	FSIZE_t	fptr;			/* File read/write pointer (Zeroed on file open) */
	DWORD	clust;			/* Current cluster of fpter (invalid when fptr is 0) */
	LBA_t	sect;			/* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
	LBA_t	dir_sect;		/* Sector number containing the directory entry (not used at exFAT) */
	BYTE*	dir_ptr;		/* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
	DWORD*	cltbl;			/* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
	BYTE	buf[FF_MAX_SS];	/* File private data read/write window */
#endif
} FIL;

FIL 结构体分析总结

FIL 是 FatFs 文件系统库中用于管理 文件对象 的核心数据结构,记录文件操作过程中的状态、位置、缓存及错误信息。其成员根据配置选项(如 FF_FS_READONLYFF_USE_FASTSEEK 等)动态调整,支持不同场景下的文件读写需求。


核心成员变量解析
成员变量 类型 说明
obj FFOBJID 文件对象标识:包含文件所属卷、起始簇号等元数据。必须是第一个成员,用于检测无效指针。
flag BYTE 文件状态标志 : - 记录文件打开模式(如 FA_READFA_WRITE)。 - 标记文件是否已关闭或发生错误。
err BYTE 错误代码 :记录最近一次文件操作的错误类型(如 FR_DISK_ERRFR_NOT_READY)。
fptr FSIZE_t 文件读写指针:当前操作位置的字节偏移量(从文件开头计算)。
clust DWORD 当前簇号 :与 fptr 对应的簇号,用于快速定位文件数据。
sect LBA_t 当前扇区号buf 中缓存的扇区号(0 表示 buf 无效)。

条件编译扩展成员
  1. !FF_FS_READONLY(读写模式支持)

    成员变量 类型 说明
    dir_sect LBA_t 目录项所在扇区:记录文件目录项的物理扇区号(exFAT 中无效)。
    dir_ptr BYTE* 目录项指针 :指向 win[] 缓存中的目录项(exFAT 中无效)。
  2. FF_USE_FASTSEEK(快速寻址支持)

    成员变量 类型 说明
    cltbl DWORD* 簇链接表:用户提供的簇号映射表,加速大文件随机访问。
  3. !FF_FS_TINY(非微小配置)

    成员变量 类型 说明
    buf BYTE[] 文件数据缓存:存储当前扇区数据,减少磁盘访问次数。

功能与工作流程

  1. 文件打开

    • 初始化 obj :从目录项中获取文件起始簇号(sclust)和大小(objsize)。

    • 设置 fptrclust :初始化读写指针为 0,clust 为起始簇号。

  2. 文件读取

    • 定位簇和扇区 :根据 fptr 计算目标簇号(通过 clust 或 FAT 表遍历)和扇区号。

    • 缓存数据 :若 sect 不匹配目标扇区,将数据读入 buf

    • 更新 fptrclust:移动读写指针,记录当前簇号。

  3. 文件写入

    • 簇分配 :若文件需要扩展,分配新簇并更新 FAT 表(依赖 dir_sectdir_ptr)。

    • 写缓存 :将数据写入 buf,标记 flag 为脏数据,适时写回磁盘。

  4. 错误处理

    • 错误记录 :操作失败时,设置 err 为错误代码(如 FR_DISK_FULL)。

    • 状态标记 :通过 flag 标记文件为错误状态,后续操作被禁止。


配置选项影响

配置宏 影响成员变量 功能扩展说明
FF_FS_READONLY dir_sect, dir_ptr 禁用目录项修改功能,减少内存占用。
FF_USE_FASTSEEK cltbl 允许用户提供簇链接表,加速大文件寻址。
FF_FS_TINY buf 禁用私有缓存,依赖外部缓冲区。

典型使用示例

cpp 复制代码
FIL fil;
FRESULT res;

// 打开文件
res = f_open(&fil, "data.txt", FA_READ);
if (res != FR_OK) {
    printf("Error: %d\n", fil.err);
    return;
}

// 读取文件内容
BYTE buffer[128];
UINT br;
res = f_read(&fil, buffer, sizeof(buffer), &br);
if (res != FR_OK) {
    printf("Read error: %d\n", fil.err);
}

// 关闭文件
f_close(&fil);

关键设计思想

  1. 缓存优化

    • buf 成员:通过缓存当前扇区数据,减少磁盘 I/O 操作。

    • sect 标记:避免重复读取同一扇区,提升性能。

  2. 快速寻址

    • cltbl 支持:用户可预先生成簇号映射表,将文件偏移直接映射到簇号,减少 FAT 表遍历开销。
  3. 错误隔离

    • errflag:明确记录错误原因和文件状态,防止错误传播。

总结

  • FIL 结构体是 FatFs 文件操作的核心,涵盖文件位置、状态、缓存及错误管理。

  • 条件编译成员支持灵活配置,适应只读、快速寻址等不同场景。

  • 读写流程 通过 fptrclustsect 协同工作,优化性能和数据一致性。

  • 错误处理机制确保操作可追溯,提升系统健壮性。

三:/* Directory object structure (DIR) */

cpp 复制代码
typedef struct {
	FFOBJID	obj;			/* Object identifier */
	DWORD	dptr;			/* Current read/write offset */
	DWORD	clust;			/* Current cluster */
	LBA_t	sect;			/* Current sector (0:Read operation has terminated) */
	BYTE*	dir;			/* Pointer to the directory item in the win[] */
	BYTE	fn[12];			/* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
	DWORD	blk_ofs;		/* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if FF_USE_FIND
	const TCHAR* pat;		/* Pointer to the name matching pattern */
#endif
} DIR;

DIR 结构体分析总结

DIR 是 FatFs 文件系统库中用于管理 目录对象 的核心数据结构,记录目录遍历过程中的状态、位置、缓存及匹配信息。其成员根据配置选项(如 FF_USE_LFNFF_USE_FIND 等)动态调整,支持目录项的读取、搜索和长文件名处理。


核心成员变量解析
成员变量 类型 说明
obj FFOBJID 目录对象标识 :包含目录所属卷、起始簇号等元数据(继承自 FFOBJID)。
dptr DWORD 目录项偏移量:当前读取/写入的目录项在目录扇区中的偏移(单位:字节)。
clust DWORD 当前簇号:目录遍历过程中当前所在的簇号(用于 FAT32/exFAT 的子目录)。
sect LBA_t 当前扇区号:目录数据所在的扇区号(0 表示遍历结束)。
dir BYTE* 目录项指针 :指向缓存(win[])中当前处理的目录项。
fn BYTE[12] 短文件名缓冲区 :存储 8.3 格式文件名(如 FILENAME.TXT)。

条件编译扩展成员
  1. FF_USE_LFN(长文件名支持)

    成员变量 类型 说明
    blk_ofs DWORD 长文件名块偏移 :当前长文件名目录项块的偏移(0xFFFFFFFF 表示无效)。
  2. FF_USE_FIND(目录搜索支持)

    成员变量 类型 说明
    pat const TCHAR* 匹配模式 :指向文件名匹配模式(如 *.txt),用于 f_findnext()

功能与工作流程

1. 目录遍历
  • 初始化

    调用 f_opendir() 打开目录时,FatFs 初始化 obj,记录目录起始簇号(根目录或子目录)。

  • 遍历过程

    • dptr 递增以遍历目录项,sectclust 定位物理扇区。

    • dir 指向当前目录项,解析文件名、属性、大小等信息。

    • sect == 0 表示遍历结束。

2. 长文件名处理
  • 多目录项拼接

    长文件名(如 "LongFileName.txt")由多个目录项组成,blk_ofs 记录当前处理的长名块偏移。

  • 编码转换

    长文件名使用 Unicode 编码(UTF-16 或 UTF-8),需配置 FF_LFN_UNICODE

3. 目录搜索
  • 模式匹配

    若启用 FF_USE_FINDpat 存储匹配模式(如 "*.txt"),f_findnext() 根据此模式过滤目录项。


配置选项影响

配置宏 影响成员变量 功能扩展说明
FF_USE_LFN blk_ofs 支持长文件名解析,需额外内存存储长名块。
FF_USE_FIND pat 支持目录搜索功能(如 f_findfirst())。
FF_FS_EXFAT (隐式影响) exFAT 目录项结构与 FAT32 不同,需特殊处理。

典型使用示例

cpp 复制代码
DIR dir;
FILINFO fno;

// 打开目录
FRESULT res = f_opendir(&dir, "/");
if (res != FR_OK) return;

// 遍历目录项
while (1) {
    res = f_readdir(&dir, &fno);
    if (res != FR_OK || fno.fname[0] == 0) break;  // 错误或遍历完成
    printf("File: %s\n", fno.fname);
}

// 关闭目录
f_closedir(&dir);

关键设计思想

  1. 高效遍历

    • dptrsect:通过偏移和扇区号快速定位目录项,减少磁盘访问。

    • dir 指针:直接操作缓存数据,避免频繁读取物理扇区。

  2. 兼容性设计

    • 短文件名兼容fn 缓冲区存储 8.3 格式文件名,兼容传统 FAT 系统。

    • 长文件名扩展 :通过 blk_ofs 支持多目录项拼接,适应现代文件系统需求。

  3. 搜索优化

    • 模式匹配pat 成员与 f_findnext() 结合,实现高效文件名过滤。

总结

  • DIR 结构体是 FatFs 目录操作的核心,涵盖目录遍历、长文件名处理和搜索功能。

  • 短文件名长文件名兼容设计,适应不同文件系统需求。

  • 条件编译成员支持灵活配置,平衡功能与资源占用。

  • 通过 dptrsectclust 协同工作,实现高效的目录项遍历。

相关推荐
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习