Fatfs f_mkdir函数分析

如果我要创建一个0:/dev的文件夹, 看一下f_mkdir是如何操作的,
首先我们要调用f_mkdir(“0:/dev”)

FRESULT f_mkdir (
	const TCHAR* path		/* Pointer to the directory path */
)
{
	FRESULT res;
	FATFS *fs;
	DIR dj;
	FFOBJID sobj;
	DWORD dcl, pcl, tm;
	DEF_NAMBUF


	res = mount_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
	/*首先根据我们传入的path = “0:/dev” 执行mount_volume函数, 
	通过vol = get_ldnumber = 0从fs = FatFs[vol]取出FATFS *指针
	对存储设备进行初始化disk_initialize(fs->pdrv), 然后读取MBR, 
	DBR区确定文件系统的类型, SectorSize, NumOfSectors, FatBase, RootDirBase, DataBase等参数*/
	if (res == FR_OK) {
		dj.obj.fs = fs;
		INIT_NAMBUF(fs);
		res = follow_path(&dj, path);			/* Follow the file path */
		/*将“0:/dev”分割为“0”, "dev", 从rootdir所在的cluster
		读取数据, 按照目录项进行解析(32Bytes固定格式), 如果找到
		了一个filename == “0”且属性为AM_DIR的目录项, 表示父级
		目录"0:"已经创建, 该目录也会在NVM上占一个Cluster的空间
		(里面存放的内容也为目录项, 代表这个目录下面的子目录或文
		件索引), 根据在rootdir中找到的目录项偏移26B找到"0:"所在
		的Cluster, 令dp->obj.sclust = "0:"所在的Cluster(代表父目录)*/
		if (res == FR_OK) res = FR_EXIST;		/* Name collision? */
		if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {	/* Invalid name? */
			res = FR_INVALID_NAME;
		}
		if (res == FR_NO_FILE) {				/* It is clear to create a new directory */
			/*这里"dev"目录没有创建*/
			sobj.fs = fs;						/* New object id to create a new chain */
			dcl = create_chain(&sobj, 0);		/* Allocate a cluster for the new directory */
			/*从Fat表中找出一个未使用的Cluster分配给"dev"目录使用*/
			res = FR_OK;
			if (dcl == 0) res = FR_DENIED;		/* No space to allocate a new cluster? */
			if (dcl == 1) res = FR_INT_ERR;		/* Any insanity? */
			if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;	/* Disk error? */
			tm = GET_FATTIME();
			if (res == FR_OK) {
				res = dir_clear(fs, dcl);		/* Clean up the new table */
				/*对这个Cluster所有的Sector进行erase*/
				if (res == FR_OK) {
					if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {	/* Create dot entries (FAT only) */
						memset(fs->win + DIR_Name, ' ', 11);	/* Create "." entry */
						fs->win[DIR_Name] = '.';
						fs->win[DIR_Attr] = AM_DIR;
						st_dword(fs->win + DIR_ModTime, tm);
						st_clust(fs, fs->win, dcl);
						memcpy(fs->win + SZDIRE, fs->win, SZDIRE);	/* Create ".." entry */
						fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
						st_clust(fs, fs->win + SZDIRE, pcl);
						fs->wflag = 1;
						/*在这个新分配给"dev"的Cluster中按目录项写入(先写入fs->win缓存, 
						同步后再写入NVM), 第一个目录项filename = ".*代表当前目录, 
						startcluster = 当前分配的Clst, 第二个目录项filename = "."代表当前
						目录的父目录, 及"0:", startcluster = dj.obj.sclust代表"0:"所在的cluster/
					}
					res = dir_register(&dj);	/* Register the object to the parent directoy */
					/*在父目录"0:"所在的Cluster中(及dj.obj.sclust)按目录项写入
					"dev"目录的信息,包括filename = "dev",  startcluster =
					 给"dev"新分配的Cluster, 这样从"0"就可以索引到其子目录"dev"*/
				}
			}
			if (res == FR_OK) {
#if FF_FS_EXFAT
				if (fs->fs_type == FS_EXFAT) {	/* Initialize directory entry block */
					st_dword(fs->dirbuf + XDIR_ModTime, tm);	/* Created time */
					st_dword(fs->dirbuf + XDIR_FstClus, dcl);	/* Table start cluster */
					st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs));	/* Directory size needs to be valid */
					st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
					fs->dirbuf[XDIR_GenFlags] = 3;				/* Initialize the object flag */
					fs->dirbuf[XDIR_Attr] = AM_DIR;				/* Attribute */
					res = store_xdir(&dj);
				} else
#endif
				{
					st_dword(dj.dir + DIR_ModTime, tm);	/* Created time */
					st_clust(fs, dj.dir, dcl);			/* Table start cluster */
					/*这里的dj.dir在经过dir_register(&dj)后指向"0"所在的
					Cluster中的一条未使用的目录项, 这里的目的及上一条注释所描述*/
					dj.dir[DIR_Attr] = AM_DIR;			/* Attribute */
					fs->wflag = 1;
				}
				if (res == FR_OK) {
					res = sync_fs(fs);
				}
			} else {
				remove_chain(&sobj, dcl, 0);		/* Could not register, remove the allocated cluster */
			}
		}
		FREE_NAMBUF();
	}

	LEAVE_FF(fs, res);
	

所以对于"0:/dev"这样一个目录. "0"的信息按照目录项存放于rootdir区, 目录本身也是一个文件, 里面按照目录项格式存放其子目录及文件信息, 也会在NVM占一个Cluster空间, 这样在f_opendir(“0:/dev”)时(如果都创建过的话), 先在rootdir区找到"0"所在的Cluster, 读取里面的内容, 找到"dev"所在的Cluster, 就可以读取"dev"下的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值