FAT的一些基础知识、概念先看我这一篇:
FAT32文件和目录的组织方式_fat32文件系统架构设计_暴躁的野生猿的博客-CSDN博客
fat文件系统的所有外部接口都在ff.h中
物理驱动器、逻辑驱动器
一个物理驱动器就是一个真实的存储设备,例如一个硬盘、一个内存卡。
逻辑驱动器就是一个虚拟概念,一个硬盘可以分成CDEF共4个盘,每个盘就是一个逻辑驱动器。
在FAT源码中有个宏 _VOLUMES,这个宏被用于配置FAT源码支持多少个逻辑驱动器。具体要配置成多少,看业务需求。
FAT源码中有个全局指针数组如上*FatFs,这个指针的每一项指向的实体就是f_mount函数的第一个形参。见下图和下文解析。
挂载:f_mount
使用文件系统的第一步,就是挂载。
函数原型:FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
static FATFS fs;
FRESULT fres = f_mount (&fs, "0:/", 1);
该函数用于从磁盘或内存卡等存储介质中,读取文件系统的信息到内存中(其实就是存到上述示例代码中的变量fs中),之后通过fs变量可以获取FAT表的物理地址、存储单元大小、该FAT所在的物理驱动器编号等信息。
path参数用于指定逻辑驱动器,所谓逻辑驱动器就类似于电脑中的"c:/"、"d:/"等盘符,在FAT文件系统中这个逻辑盘符就是"0:"、“1:”、"2:"......等。这个字符串在FAT源码中被用于匹配一个逻辑驱动器的编号。"0:"就代表第一个盘符,对应的编号为数字0。看下图,源码中是如何把字符串path转成编号变量vol的。
再看get_ldnumber函数(全名:获取逻辑驱动器编号get logical driver number)的实现:尤其关注下图红色箭头的代码,搞了半天,原来就是把字符串"0:"中冒号前面的字符减掉"0"(这是C语言基本操作,不再赘述)就得到了逻辑驱动器编号,按照这个源码的逻辑就是"0:"就对应0号,"1:"就对应1号。
上图中还有一个全局FatFs指针数组的赋值,对于"0:/"逻辑驱动器,这个驱动器的简要文件系统信息就被存到了形参fs指向的实体中,同时FatFs[0]也指向这个实体。在ff.c源码中,到处都在调用这个全局FatFs指针数组,例如格式化函数中。据此我们得知,凡是需要用到FatFs指针数组的地方,必须得在f_mount执行成功以后才行,不然就会触发野指针程序崩溃。
再回到f_mount源码截图第2个红色箭头,find_volume函数中,这个vol编号被用于索引FAT表。插播一条基础知识:每一个逻辑驱动器的前面部分,都有一个FAT表。find_volume的最终效果就是把指定逻辑驱动器的信息读取到了内存中的fs变量中。
f_mount的第三个参数是个选项,填0=稍后挂载,填1=立即挂载。编程时基本上都是填1。
格式化:f_mkfs
所谓格式化,其实就是创建FAT表,mkfs全名make file system。函数原型:
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au);
这个所做的事情,就是向存储设备中写入DBR、FAT1、FAT2,这3部分信息,详情参考文章开头的文章。