一:/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
FILINFO 结构体分析总结
FILINFO 是 FatFs 文件系统库中用于存储 文件或目录元数据 的结构体,提供文件大小、属性、时间戳及文件名等信息。其成员根据配置选项(如 FF_USE_LFN
)动态调整,支持不同文件系统的特性(如长文件名)。
核心成员变量解析
成员变量 | 类型 | 说明 |
---|---|---|
fsize |
FSIZE_t |
文件大小:以字节为单位,FSIZE_t 通常为 DWORD 或 QWORD (64位),支持大文件。 |
fdate |
WORD |
修改日期:编码为 FAT 日期格式(详见下文)。 |
ftime |
WORD |
修改时间:编码为 FAT 时间格式(详见下文)。 |
fattrib |
BYTE |
文件属性:位掩码值,如 AM_DIR (目录)、AM_RDO (只读)等。 |
altname |
TCHAR[] |
短文件名(8.3格式):仅在启用 FF_USE_LFN 时存在,用于兼容 FAT 传统格式。 |
fname |
TCHAR[] |
文件名: - FF_USE_LFN 禁用时:短文件名(fname[13] )。- FF_USE_LFN 启用时:长文件名(fname[FF_LFN_BUF+1] )。 |
关键特性说明
FAT 日期和时间编码
fdate
:16 位格式为0bYYYYYYYMMMMDDDDD
,其中:YYYYYYY
= 年 - 1980(范围 0-127,即 1980-2107)。MMMM
= 月(1-12)。DDDDD
= 日(1-31)。
ftime
:16 位格式为0bHHHHHMMMMMMSSSSS
,其中:HHHHH
= 小时(0-23)。MMMMMM
= 分钟(0-59)。SSSSS
= 秒/2(0-29,实际秒数为值×2)。
文件属性(
fattrib
)属性宏 值 说明 AM_RDO
0x01 只读文件 AM_HID
0x02 隐藏文件 AM_SYS
0x04 系统文件 AM_DIR
0x10 目录 AM_ARC
0x20 归档标记(备份用) 文件名存储
短文件名(
altname
):8.3 格式(如FILENAME.TXT
),ASCII 编码。长文件名(
fname
):Unicode(UTF-16 或 UTF-8,由FF_LFN_UNICODE
配置)。缓冲区大小:
altname
:FF_SFN_BUF + 1
(默认 13 字节,兼容 8.3 格式)。fname
:FF_LFN_BUF + 1
(默认 255 字节,支持长文件名)。
配置选项影响
配置宏 | 影响成员变量 | 功能扩展说明 |
---|---|---|
FF_USE_LFN |
altname , fname |
启用长文件名支持,同时存储短名和长名。 |
FF_LFN_UNICODE |
fname 编码 |
长文件名使用 Unicode 编码(否则为 ANSI/OEM)。 |
FILINFO 的使用场景
获取文件信息
通过f_stat()
获取文件元数据:FILINFO fno; FRESULT res = f_stat("file.txt", &fno); if (res == FR_OK) { printf("Size: %lu bytes\n", fno.fsize); printf("Name: %s\n", fno.fname); }
遍历目录项
结合f_readdir()
读取目录内容:
DIR dir;
FILINFO fno;
f_opendir(&dir, "/");
while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0) {
printf("%s\n", fno.fname);
}
f_closedir(&dir);
过滤文件类型
根据fattrib
判断是否为目录或隐藏文件:if (fno.fattrib & AM_DIR) { printf("This is a directory.\n"); } if (fno.fattrib & AM_HID) { printf("This is a hidden file.\n"); }
日期和时间解码示例
将 fdate
和 ftime
转换为可读格式:
void decode_fat_time(WORD date, WORD time) {
int year = ((date >> 9) & 0x7F) + 1980;
int month = (date >> 5) & 0x0F;
int day = date & 0x1F;
int hour = (time >> 11) & 0x1F;
int minute = (time >> 5) & 0x3F;
int second = (time & 0x1F) * 2;
printf("Last modified: %04d-%02d-%02d %02d:%02d:%02d\n",
year, month, day, hour, minute, second);
}
注意事项
长文件名配置
启用
FF_USE_LFN
会增加内存占用(需定义FF_LFN_BUF
大小)。若使用 Unicode,需确保系统编码一致(如 UTF-8)。
时间戳的局限性
FAT 时间戳精度为 2 秒(秒字段存储值为实际秒数的一半)。
不支持创建时间或访问时间(仅修改时间)。
文件名缓冲区溢出
长文件名可能超出
FF_LFN_BUF
,需合理设置缓冲区大小。
总结
FILINFO 结构体 是 FatFs 中管理文件元数据的核心,涵盖大小、时间、属性及文件名。
短文件名与长文件名 通过条件编译支持,适应不同文件系统需求。
日期和时间 需按 FAT 格式解码,属性通过位掩码判断。
典型应用 包括文件信息查询、目录遍历和文件过滤。
二:/* Format parameter structure (MKFS_PARM) */
typedef struct {
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
BYTE n_fat; /* Number of FATs */
UINT align; /* Data area alignment (sector) */
UINT n_root; /* Number of root directory entries */
DWORD au_size; /* Cluster size (byte) */
} MKFS_PARM;
成员变量分析
fmt
类型:
BYTE
作用: 指定文件系统类型。
可选值:
FM_FAT
: 传统 FAT12/FAT16 文件系统(适用于小容量存储设备)。FM_FAT32
: FAT32 文件系统(支持大分区,广泛用于 USB 驱动器和 SD 卡)。FM_EXFAT
: exFAT 文件系统(专为大文件和闪存优化,支持更大的单文件和分区)。FM_SFD
: Super Floppy 格式(将整个磁盘视为单一 FAT 卷,如软盘或某些虚拟磁盘)。
n_fat
类型:
BYTE
作用: 指定 FAT 表的数量。
典型值:
1
或2
(默认值通常为 2,用于冗余备份)。
注意:
多个 FAT 表可提高文件系统容错性(例如 FAT1 损坏时可用 FAT2 恢复)。
align
类型:
UINT
作用: 数据区对齐的扇区数。
用途:
优化磁盘访问性能(如对齐到物理扇区或 SSD 的擦除块边界)。
避免因未对齐导致的读写效率下降(尤其是在高级格式磁盘或 RAID 场景)。
n_root
类型:
UINT
作用: 根目录条目数(仅对 FAT12/16 有效)。
典型值:
FAT12/16 默认值为 512(即根目录最多存储 512 个文件/目录项)。
注意:
在 FAT32/exFAT 中,根目录为动态链表结构,此参数可能被忽略。
au_size
类型:
DWORD
作用: 簇(Cluster)的大小(字节单位)。
影响:
小簇:节省空间但增加 FAT 表大小和碎片风险。
大簇:减少碎片但浪费空间(如存储大量小文件时)。
典型值:
根据分区大小自动计算,但可手动指定(如 4096、8192 字节)。
关键设计思想
灵活性
通过组合不同参数,支持多种文件系统类型(FAT/exFAT)和存储介质(U盘、SD卡、虚拟磁盘)。
允许开发者控制底层细节(如对齐、簇大小)以优化性能或兼容性。
兼容性
FM_SFD
选项保留了传统软盘格式的支持,体现对旧设备的兼容性。n_root
的存在是为了兼容 FAT12/16 的固定根目录结构。
性能优化
align
和au_size
参数直接关联磁盘 I/O 效率,适用于对性能敏感的场景(如嵌入式系统或实时数据处理)。
典型应用场景
格式化工具
在命令行或 GUI 工具中,用户通过设置
MKFS_PARM
的参数自定义格式化行为(如指定簇大小或对齐)。例如:
mkfs.fat -F 32 -s 4096 -S 512 /dev/sda1
(对应fmt=FM_FAT32
,au_size=4096
,align=1
)。
嵌入式系统
在资源受限的设备中,通过调整参数平衡存储效率和性能(如为日志文件分配大簇以减少碎片)。
文件系统驱动开发
在实现 FAT/exFAT 驱动时,该结构体作为核心配置传递给底层格式化函数。
潜在问题与注意事项
参数冲突
某些组合可能无效(如为 exFAT 指定
n_root
会被忽略)。需根据fmt
类型验证参数合法性。
簇大小限制
FAT32 的簇大小范围受分区大小限制(如 4KB~32KB)。手动设置时需符合规范。
对齐与物理扇区
若
align
不匹配磁盘物理扇区大小(如 4K 高级格式磁盘),可能导致性能下降。
总结
MKFS_PARM
是一个高度面向文件系统底层细节的结构体,通过精确控制格式化参数,开发者可以适配不同硬件特性和应用需求。其设计体现了对 FAT 家族文件系统的历史兼容性和现代存储需求的平衡。在实际使用中,需结合具体文件系统规范和硬件特性选择参数。
三:/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
概述
FRESULT
是一个枚举类型,用于表示文件系统操作(如读写文件、目录操作、格式化等)的返回状态。它是文件系统库(如 FatFs)中的核心错误码设计,通过明确的状态值帮助开发者诊断操作失败的原因。每个枚举成员对应一种特定类型的成功或错误状态,注释中的 (n)
表示其底层整数值(例如 FR_OK
的值为 0
)。
枚举成员详解
枚举成员 | 值 | 描述 | |
---|---|---|---|
FR_OK | 0 | 操作成功。所有函数执行成功的默认返回值。 | |
FR_DISK_ERR | 1 | 底层磁盘 I/O 错误。可能是硬件故障(如存储介质损坏、连接断开)。 | |
FR_INT_ERR | 2 | 断言失败或内部逻辑错误。通常由代码缺陷或内存损坏引发。 | |
FR_NOT_READY | 3 | 物理驱动器未就绪。例如 SD 卡未插入或未初始化完成。 | |
FR_NO_FILE | 4 | 文件不存在。尝试打开或删除不存在的文件时返回。 | |
FR_NO_PATH | 5 | 路径不存在。目录路径中的某一级不存在。 | |
FR_INVALID_NAME | 6 | 路径名格式非法。包含非法字符(如 `*?<> | `)或长度超限。 |
FR_DENIED | 7 | 访问被拒绝。可能原因: - 写保护(只读文件或目录)。 - 目录已满(无法创建新文件)。 |
|
FR_EXIST | 8 | 文件/目录已存在。尝试创建同名文件或目录时返回。 | |
FR_INVALID_OBJECT | 9 | 文件/目录对象无效。例如已关闭的文件句柄被重复使用。 | |
FR_WRITE_PROTECTED | 10 | 物理驱动器写保护。例如 SD 卡的写保护开关开启。 | |
FR_INVALID_DRIVE | 11 | 无效的逻辑驱动器号。指定的驱动器编号超出范围。 | |
FR_NOT_ENABLED | 12 | 卷未挂载或工作区未分配。需先调用 f_mount 挂载文件系统。 |
|
FR_NO_FILESYSTEM | 13 | 未找到有效的文件系统。分区未格式化或格式不被支持(如非 FAT/exFAT)。 | |
FR_MKFS_ABORTED | 14 | 格式化操作中止。可能因参数错误或磁盘问题导致无法完成格式化。 | |
FR_TIMEOUT | 15 | 访问超时。在多任务环境中等待资源锁超时。 | |
FR_LOCKED | 16 | 文件被锁定。因文件共享策略禁止操作(如其他进程占用文件)。 | |
FR_NOT_ENOUGH_CORE | 17 | 内存不足。无法为长文件名(LFN)分配缓冲区。 | |
FR_TOO_MANY_OPEN_FILES | 18 | 打开文件数超限。超过系统配置的最大同时打开文件数(FF_FS_LOCK )。 |
|
FR_INVALID_PARAMETER | 19 | 参数非法。调用函数时传入无效参数(如空指针或越界值)。 |