FatFs 0.01学习笔记
2014年2月14日
9:20
——何小龙
博客:http://blog.csdn.net/hexiaolong2009
一、介绍:
本文以网上开源文件系统FatFs 0.01为研究对象,剖析FatFs文件系统的核心操作。FatFs目前最新版本已更新到0.10a版
本,而我之所以选择0.01版本,是因为这是最早的发布版本,与最新的版本相比,去掉了很多高级应用,且代码量
相对较小,宏开关也少了许多,易于阅读和理解,用来研究它的雏形再合适不过了,所以笔者选择0.01版本进行剖
析。当大家了解了0.01的核心思想后,再回去看最新的版本,也就容易理解多了。
FatFs历史版本下载:http://elm-chan.org/fsw/ff/00index_e.html 在官网的最下面,能找到所有版本的下载链接。
二、重点:
1. FatFs中有两个重要的缓冲区:win[]和buffer。win[]在FATFS结构体中,buffer在FIL结构体中。
win[]:系统缓冲区。当操作MBR,DBR,FAT表,根目录区时,使用该缓冲区;
buffer:文件缓冲区。当对文件的内容进行操作时,如读、写、修改时,才使用该缓冲区。
2. 在对文件的f_read和f_write过程中(不考虑f_lseek的情况),只有需要读写的最后一个扇区(内容小于512字节)
才会被暂存到buffer中,而前面的扇区内容是直接通过磁盘驱动disk_read/disk_write在用户缓冲区和物理磁盘之间进
行交互的。
注意:FatFs 0.01与最新的版本还是不少差异的,如在0.01中,buffer只是个指针,需要用户自己定义文件缓冲区,并
将buffer指向该缓冲区。而最新版本中,FIL已经有自己的buf[_MAX_SS]。在0.01中没有f_mount()函数,所以需要手动
将全局指针FatFs指向自己定义的变量fs。具体的操作流程可参考官网上的示例代码。
三、关键函数总结:
1. f_open
f_open()
{
1. 初始化SD卡,初始化FATFS对象;
2. 查找文件的目录项;
3. 填充文件结构体FIL。
}
2. f_read
f_read()
{
1. 从物理磁盘直接读取所需扇区到用户缓冲区,这个过程中未使用buffer缓冲区;
2. 如果最后一扇区要读取的字节数少于512,则先将最后一扇区读到buffer中,然后再从buffer拷贝需要的字节
到用户缓冲区中。
}
FatFs学习笔记 Page 1
FatFs文件系统
SD卡物理空间
系统缓冲区
512Bytes
move _window ()
1
由disk_read直接
读取连续扇区
文件缓冲区
512Bytes
2
读取最后一扇区
到buffer
win[]
buffer
文件目录项对应的扇区
…
…
扇区0
扇区1
……
扇区0
扇区1
……
扇区0
扇区1
……
…
…
文
件
实
际
大
小
第n簇
第n+1簇
第n+2簇
用户缓冲区
大小由用户定义
3
再从buffer拷贝
到用户缓冲区
3. f_write
f_write()
{
1. 从用户缓冲区直接写入到物理磁盘,这个过程中未使用buffer缓冲区;
2. 如果要写入的最后一扇区内容少于512字节,则先从物理磁盘读取最后一扇区的内容到buffer中,然后修改
buffer中的相应内容,并设置回写标记,这样下次调用f_close/f_write时,就会将buffer回写到物理磁盘中。
}
FatFs学习笔记 Page 2
FatFs文件系统
SD卡物理空间
系统缓冲区
512Bytes
move _window ()
1
由disk_write直
接写入连续扇区
文件缓冲区
win[]
buffer
先读取最后一扇
区到buffer中
2
文件目录项对应的扇区
…
…
扇区0
扇区1
……
扇区0
扇区1
……
扇区0
扇区1
……
…
…
文
件
实
际
大
小
第n簇
第n+1簇
第n+2簇
用户源缓冲区
512的整数倍
再从源缓冲区拷
贝到buffer中
3
不足1个扇区的内容
4. f_close
关键是调用了f_sync函数。
5. f_sync
f_sync()
{
1. 将buffer回写到物理磁盘中;
2. 读取文件对应的目录项到win[]中,更新参数,并回写。
}
FatFs学习笔记 Page 3
FatFs文件系统
SD卡物理空间
系统缓冲区
2
文件目录项对应的扇区
文件对应的
目录项
move _window()
3
win[]
用户源缓冲区
文件缓冲区
512的整数倍
不足1个扇区的内容
不足1个扇区的内容
1
disk_write()
buffer
…
…
扇区0
扇区1
……
扇区0
扇区1
……
扇区0
扇区1
……
…
…
文
件
实
际
大
小
第n簇
第n+1簇
第n+2簇
5. move_window
move_window专用于操作win[]系统缓冲区。
move_window(B);
调用前:
FatFs学习笔记 Page 4
FATFS *FatFs
SD卡物理空间
FATFS fs;
BYTE
BYTE
BYTE
BYTE
fs_type
files
sects_clust
n_fats
WORD
n_rootdir
BYTE
BYTE
dirtyflag = 1
pad1
DWORD sects_fat
DWORD max_clust
DWORD fatbase
DWORD dirbase
DWORD database
DWORD winsect = A
BYTE
win[512]
扇区A
(Modified)
扇区A
……
扇区B
执行中:
FATFS *FatFs
SD卡物理空间
FATFS fs;
BYTE
BYTE
BYTE
BYTE
fs_type
files
sects_clust
n_fats
1
WORD
n_rootdir
判断是否修改过
BYTE
BYTE
dirtyflag = 1
pad1
DWORD sects_fat
DWORD max_clust
DWORD fatbase
DWORD dirbase
DWORD database
DWORD winsect = A
BYTE
win[512]
2
disk_write
扇区A
……
扇区B
扇区A
(Modified)
disk_read
3
调用后:
FatFs学习笔记 Page 5
FATFS *FatFs
SD卡物理空间
FATFS fs;
BYTE
BYTE
BYTE
BYTE
fs_type
files
sects_clust
n_fats
WORD
n_rootdir
BYTE
BYTE
dirtyflag = 0
pad1
DWORD sects_fat
DWORD max_clust
DWORD fatbase
DWORD dirbase
DWORD database
DWORD winsect = B
BYTE
win[512]
扇区B
扇区A
(Modified)
……
扇区B
四、源码注释
本人在不破坏源码逻辑的前提下,对FatFs 0.01源代码进行了中文注释,个别函数重新修改了排版布局,以方便阅
读。结合以上示意图即伪代码,相信大家会很快理解FatFs 0.01的核心思想及架构。
源码如下:
ff
ff
FatFs学习笔记 Page 6