
鸿蒙轻内核M核源码分析系列二一 04 文件系统FatFS 原创 精华
鸿蒙轻内核M核源码分析系列二一 04 文件系统FatFS
【本文正在参与优质创作者激励】
FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的比特数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。LiteOS-M内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。LiteOS-M内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。
本文先介绍下FatFS文件系统结构体的结构体和全局变量,然后分析下FatFS文件操作接口。文中所涉及的源码,均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。
1、FatFS文件系统结构体介绍
会分2部分来介绍结构体部分,先介绍FatFS文件系统的结构体,然后介绍LiteOS-M内核中提供的和FatFS相关的一些结构体。
1.1 FatFS的结构体
在openharmony/third_party/FatFs/source/ff.h头文件中定义FatFS的结构体,我们先简单了解下,后文会使用到的。
先看下相关的宏定义,包含文件访问模式(File access mode),格式化选项(Format options)等等。文件打开方式和POSIX文件打开选项不一致,需要转换,后文会涉及。
在openharmony/third_party/FatFs/source/ffconf.h头文件中定义FatFS的一些配置信息。如下文的驱动和卷的配置信息等。对于LiteOS-M,默认是支持4个卷。宏定义FS_MAX_SS表示扇区大小sector size。
对于适配LiteOS-M内核的开发板,使用FatFS文件系统时,需要提供头文件liteos_m\board\fs\fs_config.h,例如:openharmony\device\qemu\arm_mps2_an386\liteos_m\board\fs\fs_config.h。
接下来看看重要的结构体。结构体FATFS是FatFS文件系统类型结构体。成员变量BYTE fs_type等0时表示未挂载,挂载后一般取值为FS_FAT12、FS_FAT16或FS_FAT32;WORD id表示卷的挂载编号。 其他成员变量可以暂不了解。
结构体FIL、DIR分别是FatFS的文件和目录类型结构体,DIR是__dirstream结构体的别名,一般在Musl或Newlib C库的文件dirent.h会有typedef struct __dirstream DIR;
。这两个结构体都包含FFOBJID obj这个成员变量,FFOBJID结构体体包含FATFS* fs成员,可以关联文件卷信息。暂不需要关心其他成员变量细节,知道结构体的用途即可。
结构体FILINFO用于维护文件信息,包含文件修改时间,大小和文件名等信息。
1.2 LiteOS-M FatFS的结构体
我们来看下在文件components\fs\fatfs\fatfs.c里定义的结构体。结构体FatHandleStruct维护文件相关的信息,该结构体非常简单,在FIL的基础上增加了是否使用成员变量。
2、LiteOS-M FatFS的重要全局变量及操作
了解下文件components\fs\fatfs\fatfs.c中定义的常用全局变量。⑴处的g_handle数组维护文件信息,默认支持的文件数目为FAT_MAX_OPEN_FILES;g_dir数组维护目录信息,默认支持的目录数目为FAT_MAX_OPEN_DIRS。 ⑵处的g_fatfs数组维护每个卷的的文件系统信息,默认文件卷数目FF_VOLUMES为4个。和文件卷相关的变量还有g_volPath数组维护每个卷的字符串路径,g_volWriteEnable数组维护每个卷是否可写。⑶处的g_workBuffer维护每个扇区的缓存。⑷处开始的g_fileNum、g_dirNum分别是文件和目录打开的数目;struct dirent g_retValue是目录项结构体变量,用于函数fatfs_readdir();pthread_mutex_t g_fsMutex是互斥锁变量;⑸处开始的挂载操作变量g_fatfsMnt、文件操作操作全局变量g_fatfsFops,在虚拟文件系统中被使用。
下文继续介绍下和这些变量相关的内部操作接口。
2.1 文件系统互斥锁
FatFS文件系统使用的是超时加锁。函数FsLock()中,⑴处获取系统实时时间,⑵处设置15秒超时,FS_LOCK_TIMEOUT_SEC默认为15秒。⑶处对互斥量进行加锁,超时后不会再对互斥量加锁。函数FsUnlock()用于解锁。
2.2 判断文件描述符有效性
函数IsValidFd()用于判断文件描述符的是否有效,如果文件描述符超出有效范围,或者文件未使用状态,返回false,否则返回true。
2.3 切换驱动器
函数FsChangeDrive()根据传入的路径切换驱动器(盘符)。字符串数组tmpPath用于保存驱动器名称,其中驱动器名称最大值FS_DRIVE_NAME_MAX_LEN。⑵处处理路径长度大于驱动器名称长度的情况。⑶处从路径中获取驱动器名称,然后调用接口f_chdrive()切换驱动器。在文件操作接口中,会调用该函数来切换驱动器,如fatfs_open、fatfs_unlink、fatfs_stat、fatfs_mkdir、fatfs_opendir、fatfs_rmdir、fatfs_rename和fatfs_statfs,这些函数的参数涉及文件路径char *path或者目录char *dirName。
2.4 匹配文件卷
函数FsPartitionMatch()根据传入的文件路径获取对应的卷索引,在挂载、卸载、格式化等接口中使用。⑴处如果传入的是卷名称,获取顶级目录名称,即路径的第一级目录,前后不包含路径分隔符/。⑵如果传入的是路径名称,获取顶级路径,截止到第一个分隔符/。否则执行⑶,赋值路径中的名称。然后遍历每一个卷,如果获取的顶级目录名称等于卷名称,则返回对应的卷数组索引。否则返回FS_FAILURE。
2.4 判断文件卷是否可写
函数FsCheckByPath()、FsCheckByID()用于判断文件卷是否可写,传递参数不同。前者传入的是文件路径,转化为卷索引后判断。后者传入的是挂载编号,遍历每一个卷,判断相应卷的编号与传入参数是否相等。
2.5 标签转换
函数FatFsGetMode()用于把POSIX格式的文件打开标签转换为FatFS文件系统格式的文件打开标签。FatfsErrno()把FatFS文件系统格式的错误号转换为POSIX格式的错误号。
