如果我要创建一个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"下的内容