fatfs文件系统详解之f_open函数分析

本文深入解析f_open函数,探讨如何创建和打开文件,包括FAT32文件系统中关键结构体的使用,如DIR和FIL,以及f_open函数内部流程,如路径追踪和目录项匹配。

前序

前面分析了f_mkfs、f_mount函数,在格式化和挂载完成之后,当然是要创建文件的操作,本节分析f_open函数,分析一下创建和打开一个文件时,发生了什么。

分析假设

(1)假设一个磁盘就一个分区。

(2)只分析FAT32文件系统相关的代码。

(3)函数的大部分分析,都写入代码注释中。

(4)重要的注释都回加入很多星号以及数学标号。例如,
/
****************** 1.把字符存入lfn的buffer中 *******************/

关键结构体

(1)FAT文件系统描述一个文件夹的结构体。虽然是一个文件夹结构体,但是再打开一个文件的开始,先创建这个结构体,然后先把文件的信息填充到这个结构体,最终使用这个结构体填充FIL结构图的一些重要信息。

typedef struct {
   
   
	_FDID	obj;			/* 存放下一个目标的信息 */
	DWORD	dptr;			/* 当前目录项的起始地址(单位:字节) */
	DWORD	clust;			/* 当前簇 */
	DWORD	sect;			/* 当前簇对应的扇区位置(通过目录项的位置确定) */
	BYTE*	dir;			/* 指向当前扇区win[]中的偏移(单位:字节) */
	BYTE	fn[12];			/* 存放8.3文件名,最后1个字节存放标志:是否有长目录项 */
#if _USE_LFN != 0
	DWORD	blk_ofs;		/* 指向第1个长目录项的起始位置(字节:单位) (0xFFFFFFFF:Invalid) */
#endif
#if _USE_FIND
	const TCHAR* pat;		/* Pointer to the name matching pattern */
#endif
} DIR;

(2)FAT文件系统描述一个文件的结构图。

typedef struct {
   
   
	_FDID	obj;			/* 存放下一个目标的信息 */
	BYTE	flag;			/* 文件状态标志 */
	BYTE	err;			/* 文件错误码 */
	FSIZE_t	fptr;			/* 文件的读写指针位置 */
	DWORD	clust;			/* fptr所在的当前簇 */
	DWORD	sect;			/* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
	DWORD	dir_sect;		/* Sector number containing the directory entry */
	BYTE*	dir_ptr;		/* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
	DWORD*	cltbl;			/* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !_FS_TINY
	BYTE	buf[_MAX_SS];	/* File private data read/write window */
#endif
} FIL;

(3)_FDID结构体。
在(1)和(2)的结构体中,都有_FDID结构体,那么分析一下这个结构体的内容:
注:在FATFS中有个全局的指针数组FATFS[],在f_mount的时候可知,这个数组会被填充,填充的内容是MBR的内容,之后,我们把这个数组指针称作为**“超级快”**。

typedef struct {
   
   
	FATFS*	fs;			/* 指向全局的在挂载的时候磁盘对应的超级块 */
	WORD	id;			/* Owner file system mount ID */
	BYTE	attr;		/* 目标属性,根据目录项中的属性进行填充 */
	BYTE	stat;		/* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
	DWORD	sclust;		/* 目标的起始簇号 */
	FSIZE_t	objsize;	/* 文件或者文件夹的大小 */
#if _FS_LOCK != 0
	UINT	lockid;		/* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;

f_open函数分析
下面是f_open的源代码:

FRESULT f_open (
	FIL* fp,			/* 返回的文件描述符 */
	const TCHAR* path,	/* 打开文件的路径 */
	BYTE mode			/* 文件打开的模式 */
)
{
   
   
	FRESULT res;
	DIR dj; /* 分配一个DIR结构体 */
	FATFS *fs;
#if !_FS_READONLY
	DWORD dw, cl, bcs, clst, sc;
	FSIZE_t ofs;
#endif

	if (!fp) return FR_INVALID_OBJECT;

	/* Get logical drive */
	mode &= _FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND | FA_SEEKEND;
	res = find_volume(&path, &fs, mode);
	if (res == FR_OK) {
   
   
		dj.obj.fs = fs;
        /* 根据不同的配置来分配fs->lfn,用于存放path指向的路径 */
		INIT_NAMBUF(fs);
		res = follow_path(&dj, path);	/* Follow the file path */
#if !_FS_READONLY	/* R/W configuration */
		if (res == FR_OK) {
   
   
			if (dj.fn[NSFLAG] & NS_NONAME) {
   
   	/* Origin directory itself? */
				res = FR_INVALID_NAME;
			}
#if _FS_LOCK != 0
			else {
   
   
				res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
			}
#endif
		}
		/* Create or Open a file */
		if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
   
   
			if (res != FR_OK) {
   
   
                /* 文件不存在 创建文件,省略不少代码 */
            }
			else {
   
   
                /* 文件存在 但是不允许写入 */
				if (dj.obj.attr & (AM_RDO | AM_DIR
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值