文件系统分析了两天,自己都不知道入没入门,现在就把这两天分析的结果总结一下吧!
一、res = f_mount(0,&fs); 首先是挂接根文件系统,为什么要挂接根文件系统内容?因为根文件系统里面会对我们的SD卡进行初始化,除此之外
f_mount函数可以实现在FatFs模块上注册/ 注销一个工作区。 在使用任何其他文件函数之前,必须使用该函数为每个
卷注册一个工作区。要注销一个工作区,只要指定FileSystemObject 为NULL即可,然后该工作区可以被丢
弃。 该函数只初始化给定的工作区,以及将该工作区的地址注册到内部表中,不访问磁盘I/O 层。卷装入过程是在
f_mount函数后或存储介质改变后的第一次文件访问时完成的。
接着分析这个函数是怎么定义的:
[csharp] view plain copy
print?
- /********************************************************************************
- * 函数名称: f_mount
- * 函数说明: 用于挂载/卸载磁盘驱动器
- * 输入参数: vol:Logical drive number to be mounted/unmounted
- * fs:Pointer to new file system object (NULL for unmount)
- * 返回参数: 挂载标识FR_OK表示成功!
- * 注意事项: 无
- *********************************************************************************/
- FRESULT f_mount (
- BYTE vol, /* Logical drive number to be mounted/unmounted */
- FATFS *fs /* */
- )
- {
- FATFS *rfs;
-
-
-
-
- if (vol >= _VOLUMES) /* Check if the drive number is valid */ //如果
- return FR_INVALID_DRIVE;
- rfs = FatFs[vol]; /* Get current fs object */
-
-
- if (rfs) {
- #if _FS_LOCK
- clear_lock(rfs);
- #endif
- #if _FS_REENTRANT /* Discard sync object of the current volume */
- if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
- #endif
- rfs->fs_type = 0; /* Clear old fs object */
- }
-
-
- if (fs) {
- fs->fs_type = 0; /* Clear new fs object */
- #if _FS_REENTRANT /* Create sync object for the new volume */
- if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
- #endif
- }
- FatFs[vol] = fs; /* Register new fs object */
-
-
- return FR_OK;
- }
1、vol = 0,fs = &fs 首先看这个rfs = FatFs[vol];/* Get current fs object */
2、接着我们看到这个 FATFS *FatFs[_VOLUMES],从而知道了FatFs[vol]指向的是个 FATFS类型的结构体
那么到底FATFS的原型是什么呢?看下面!这是去除宏定义精简之后的结构体成员。
[csharp] view plain copy
print?
- typedef struct {
- BYTE fs_type; /* FAT sub-type (0:Not mounted) */
- BYTE drv; /* Physical drive number */
- BYTE csize; /* Sectors per cluster (1,2,4...128) */
- BYTE n_fats; /* Number of FAT copies (1,2) */
- BYTE wflag; /* win[] dirty flag (1:must be written back) */
- BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
- WORD id; /* File system mount ID */
- WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
- DWORD last_clust; /* Last allocated cluster */
- DWORD free_clust; /* Number of free clusters */
- DWORD fsi_sector; /* fsinfo sector (FAT32) */
- DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
- DWORD fsize; /* Sectors per FAT */
- DWORD fatbase; /* FAT start sector */
- DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
- DWORD database; /* Data start sector */
- DWORD winsect; /* Current sector appearing in the win[] */
- BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ //存放的就是我们读SD卡第一扇区的内容
- } FATFS;
到这里我们就可以推断出rfs也应该是FATFS*类型的,所以可以通过rfs ->drv的方法去访问文件系统的各项参数了。下面验证一下:
3、确实在ff.c文件的f_mount函数里面定义了一个这样的变量
FATFS *rfs;
从而验证了我们的猜想。总结一下这几句话的作用
if (vol >= _VOLUMES)/* Check if the drive number is valid */
return FR_INVALID_DRIVE;
rfs = FatFs[vol];/* Get current fs object */
我的理解:挂载的目的就是为了给rfs分配地址,假如没有使用到内存管理malloc的话,使用这种方法也可以的。但是这里的rfs还是NULL的。
4、接着我们可以看看下面的代码,这也是去除了相关宏定义之后的代码
[csharp] view plain copy
print?
- if (rfs) {
- rfs->fs_type = 0; /* Clear old fs object */
- }
- if (fs) {
- fs->fs_type = 0; /* Clear new fs object */
- }
- FatFs[vol] = fs; /* Register new fs object */
- return FR_OK;
分析:
a、非零为真,那么在这里rfs这个地址肯定是空的,因为给rfs赋值就是NULL。
b、那么fs又是什么东西呢?看传入参数可以知道:fs = &fs ,因为之前这个是定义过了的:FATFS *rfs;。
明显的知道我们传入的fs不为NULL的,所以自然执行了fs->fs_type = 0;将类型清零,只不过,这个类型是
我在主函数里面使用的(新的),那么清零到底表示什么意思呢?其实是有说明的FAT sub-type (0:Not mounted)
这就是表示卸载的意思!
c、好的,卸载掉旧的,那么就可以注册新的了, FatFs[vol] = fs;/* Register new fs object */
总结一下这上面几行代码的作用:
我的理解:就是实现了挂载文件系统的目标文件,也就是给它分配了一个地址空间。而FatFs[vol]这个指针会被其他的ff.c里面的函数调用的
|