fatfs开源文件系统,不再赘述,笔者主要做嵌入式方向,最近对文件管理感兴趣,说白了对于CPU来说无论是磁盘,ram等输入输出都是0101的数据,sd中也是存储的010的数据,只是最后经过文件系统的解析到我们用户手中便变成了我们可以看到的字符串,汉字,图片等等。于是打算深入学习下fatfs,这种东西就是一通百通的东西,下面进行实际的分析。
ok先看文件系统的数据结构,比较重要的我们需要分析的已经被汉语标注,其他的看英文就懂了,这里的还需要读者去看下Fat的基本原理,也附上链接源码的分析
typedef struct {
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] 每个簇的扇区个数,所以簇的地址就是数据开始地址 + 簇的num * 扇区个数 * 512*/
#if FF_USE_LFN
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] fat表的大小 每个数据用32字节*/
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector FAT表,当数据大于一个簇的大小时需要制定下一个簇在哪里*/
DWORD dirbase; /* Root directory base sector/cluster 根目录扇区在哪里 计算实际地址时需要 dirbase * 512 //因为一个扇区固定大小512byte*/
DWORD database; /* Data base sector 数据扇区在哪里*/
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
其次我们需要分析的数据结构是存储文件信息的,这样我们根据这个以及上面的数据结构就能在sd的二进制文件中找到我们存储的数据了
/* File object structure (FIL) */
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) 当前操作的簇 */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) 开始扇区*/
#if !FF_FS_READONLY
DWORD 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;
我们以我们存在根目录下的result.txt为例分析。
存放的数据为
只关心前面正常的数据就行了,测试代码也是网上下载的,嘻嘻嘻。。。。
ok我们在sdk下进行f_open, f_write,然后debug看这两个数据结构的数据如下:
ok,此时我们可以看到(注意每个sd卡可能不一样,每个这样分析就可以了)
n_fat:文件系统fat表个数为2个
csize:每个簇里面一个扇区,512字节
dirbase:目录开始扇区为2,转化为地址就是2512=0x400
fatbase:fat表的开始扇区为0x307e,转换为地址就是0x307e512=0x60Fc00
database:数据开始扇区为0x4000,也就是说从这里开始簇开始计数0,1,2,3,这里的实际地址是0x4000512=0x800000
在来看fil:
看文件的目录地址:dirbase = 0x4000512 = 0x800000
sec:开始时0x4005,地址是0x4005*512 = 0x800a00如下