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 协同工作,实现高效的目录项遍历。

相关推荐
19岁开始学习1 小时前
Go学习-入门
开发语言·学习·golang
ianozo2 小时前
CTF 代码学习日记 PHP
java·学习·php
大G哥2 小时前
用DeepSeek来帮助学习three.js加载3D太极模形
开发语言·前端·javascript·学习·ecmascript
没有不重的名么2 小时前
MATLAB基础学习相关知识
数据结构·学习·matlab
omage3 小时前
cornerstone3D学习笔记-MPR
笔记·学习·vtk·dicom·mpr
虾球xz3 小时前
游戏引擎学习第114天
学习·游戏引擎
虾球xz4 小时前
游戏引擎学习第109天
学习·游戏引擎
Moonnnn.7 小时前
C语言——时基
c语言·笔记·学习
李长渊哦7 小时前
学习 `@PreDestroy`:Java EE/Jakarta EE 生命周期回调
java·学习·java-ee
人有一心8 小时前
cs224w课程学习笔记-第2课
笔记·学习