鴻蒙內核M核源碼分析系列二一 03 文件系統FatFS(2)

      網友投稿 773 2025-03-31

      2.4 判斷文件卷是否可寫


      函數FsCheckByPath()、FsCheckByID()用于判斷文件卷是否可寫,傳遞參數不同。前者傳入的是文件路徑,轉化為卷索引后判斷。后者傳入的是掛載編號,遍歷每一個卷,判斷相應卷的編號與傳入參數是否相等。

      static bool FsCheckByPath(const char *path) { INT32 index; index = FsPartitionMatch(path, PATH_NAME); if (index == FS_FAILURE) { return FS_FAILURE; } return g_volWriteEnable[index]; } static bool FsCheckByID(int id) { INT32 index; for (index = 0; index < FF_VOLUMES; index++) { if (g_fatfs[index].id == id) { return g_volWriteEnable[index]; } } return false; }

      2.5 標簽轉換

      函數FatFsGetMode()用于把POSIX格式的文件打開標簽轉換為FatFS文件系統格式的文件打開標簽。FatfsErrno()把FatFS文件系統格式的錯誤號轉換為POSIX格式的錯誤號。

      static unsigned int FatFsGetMode(int oflags) { UINT32 fmode = FA_READ; if ((UINT32)oflags & O_WRONLY) { fmode |= FA_WRITE; } if (((UINT32)oflags & O_ACCMODE) & O_RDWR) { fmode |= FA_WRITE; } /* Creates a new file if the file is not existing, otherwise, just open it. */ if ((UINT32)oflags & O_CREAT) { fmode |= FA_OPEN_ALWAYS; /* Creates a new file. If the file already exists, the function shall fail. */ if ((UINT32)oflags & O_EXCL) { fmode |= FA_CREATE_NEW; } } /* Creates a new file. If the file already exists, its length shall be truncated to 0. */ if ((UINT32)oflags & O_TRUNC) { fmode |= FA_CREATE_ALWAYS; } return fmode; } static int FatfsErrno(int result) { INT32 status = 0; if (result < 0) { return result; } /* FatFs errno to Libc errno */ switch (result) { case FR_OK: break; case FR_NO_FILE: case FR_NO_PATH: case FR_NO_FILESYSTEM: status = ENOENT; break; ...... default: status = result; break; } return status; }

      3、LiteOS-M FATFS的文件系統操作接口

      快速記錄下各個操作接口,對每個接口的用途用法不再描述??梢詤⒖贾暗南盗形恼?,《鴻蒙輕內核M核源碼分析系列十九 Musl LibC》中介紹了相關的接口,那些接口會調用VFS文件系統中操作接口,然后進一步調用FatFS文件操作接口。

      3.1 掛載和卸載操作

      先看下掛載操作,FatFS支持重新掛載操作。如果掛載選項包含MS_REMOUNT時,會調用函數Remount()重新掛載。函數Remount()中,⑴處調用FsPartitionMatch()獲取卷索引,⑵處如果卷未被掛載,不允許重新掛載,返回錯誤碼。⑶處設置對應的卷是否可讀可寫標記。由此看來,重新掛載,主要是更新卷的可讀可寫能力。

      看下掛載函數fatfs_mount(),⑷處開始判斷參數有效性,不能為空,文件系統類型必須為“fat”,⑸處調用FsPartitionMatch()獲取卷索引,⑹處如果卷已經被掛載,則返回錯誤碼。⑺處調用f_mount()實現掛載,第3個參數1表示立即掛載。⑻設置對應的卷是否可讀可寫標記。

      static int Remount(const char *path, unsigned long mountflags) { INT32 index; ⑴ index = FsPartitionMatch(path, PART_NAME); if (index == FS_FAILURE) { PRINTK("Wrong volume path!\r\n"); errno = ENOENT; return FS_FAILURE; } /* remount is not allowed when the device is not mounted. */ ⑵ if (g_fatfs[index].fs_type == 0) { errno = EINVAL; return FS_FAILURE; } ⑶ g_volWriteEnable[index] = (mountflags & MS_RDONLY) ? FALSE : TRUE; return FS_SUCCESS; } ...... int fatfs_mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) { INT32 index; FRESULT res; INT32 ret; ⑷ if ((target == NULL) || (filesystemtype == NULL)) { errno = EFAULT; return FS_FAILURE; } ret = FsLock(); if (ret != 0) { errno = ret; return FS_FAILURE; } if (mountflags & MS_REMOUNT) { ret = Remount(target, mountflags); goto OUT; } if (strcmp(filesystemtype, "fat") != 0) { errno = ENODEV; ret = FS_FAILURE; goto OUT; } ⑸ index = FsPartitionMatch(target, VOLUME_NAME); if (index == FS_FAILURE) { errno = ENODEV; ret = FS_FAILURE; goto OUT; } /* If the volume has been mounted */ ⑹ if (g_fatfs[index].fs_type != 0) { errno = EBUSY; ret = FS_FAILURE; goto OUT; } ⑺ res = f_mount(&g_fatfs[index], target, 1); if (res != FR_OK) { errno = FatfsErrno(res); ret = FS_FAILURE; goto OUT; } ⑻ g_volWriteEnable[index] = (mountflags & MS_RDONLY) ? FALSE : TRUE; ret = FS_SUCCESS; OUT: FsUnlock(); return ret; }

      接下來,看下卸載操作。函數fatfs_umount()中,先進行參數有效性,是否掛載等基礎檢查,⑴處調用函數f_checkopenlock()來判斷要卸載的卷中是否有打開的文件或目錄,⑵處調用f_mount(),第一個參數為NULL,表示卸載target指定的文件系統;,第3個參數0表示不需要掛載。如果卸載錯誤,轉換相應的錯誤碼。⑶處如果磁盤訪問窗口(Disk access window for Directory)不為空,執行相應的釋放操作。⑷處把文件卷數組對應的元素置零。

      函數CloseAll()根據文件卷編號,遍歷每一個打開的文件和目錄進行關閉。函數fatfs_umount2()中,⑸處表示支持的卸載選項有:MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW。⑹處處理強制卸載的情形,會首先關閉打開的文件和目錄,然后再去執行⑺實現卸載操作。

      int fatfs_umount(const char *target) { FRESULT res; INT32 ret; INT32 index; if (target == NULL) { errno = EFAULT; return FS_FAILURE; } ret = FsLock(); if (ret != 0) { errno = ret; return FS_FAILURE; } index = FsPartitionMatch(target, VOLUME_NAME); if (index == FS_FAILURE) { errno = ENOENT; ret = FS_FAILURE; goto OUT; } /* The volume is not mounted */ if (g_fatfs[index].fs_type == 0) { errno = EINVAL; ret = FS_FAILURE; goto OUT; } /* umount is not allowed when a file or diretory is opened. */ ⑴ if (f_checkopenlock(index) != FR_OK) { errno = EBUSY; ret = FS_FAILURE; goto OUT; } ⑵ res = f_mount((FATFS *)NULL, target, 0); if (res != FR_OK) { errno = FatfsErrno(res); ret = FS_FAILURE; goto OUT; } ⑶ if (g_fatfs[index].win != NULL) { ff_memfree(g_fatfs[index].win); } ⑷ (void)memset_s(&g_fatfs[index], sizeof(FATFS), 0x0, sizeof(FATFS)); ret = FS_SUCCESS; OUT: FsUnlock(); return ret; } static int CloseAll(int index) { INT32 i; FRESULT res; for (i = 0; i < FAT_MAX_OPEN_FILES; i++) { if (g_fileNum <= 0) { break; } if ((g_handle[i].useFlag == 1) && (g_handle[i].fil.obj.fs == &g_fatfs[index])) { res = f_close(&g_handle[i].fil); if (res != FR_OK) { errno = FatfsErrno(res); return FS_FAILURE; } (void)memset_s(&g_handle[i], sizeof(FatHandleStruct), 0x0, sizeof(FatHandleStruct)); g_fileNum--; } } for (i = 0; i < FAT_MAX_OPEN_DIRS; i++) { if (g_dirNum <= 0) { break; } if (g_dir[i].obj.fs == &g_fatfs[index]) { res = f_closedir(&g_dir[i]); if (res != FR_OK) { errno = FatfsErrno(res); return FS_FAILURE; } (void)memset_s(&g_dir[i], sizeof(DIR), 0x0, sizeof(DIR)); g_dirNum--; } } return FS_SUCCESS; } int fatfs_umount2(const char *target, int flag) { INT32 index; INT32 ret; UINT32 flags; FRESULT res; if (target == NULL) { errno = EFAULT; return FS_FAILURE; } ⑸ flags = MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW; if ((UINT32)flag & ~flags) { errno = EINVAL; return FS_FAILURE; } ret = FsLock(); if (ret != 0) { errno = ret; return FS_FAILURE; } index = FsPartitionMatch(target, VOLUME_NAME); if (index == FS_FAILURE) { errno = ENOENT; ret = FS_FAILURE; goto OUT; } /* The volume is not mounted */ if (g_fatfs[index].fs_type == 0) { errno = EINVAL; ret = FS_FAILURE; goto OUT; } ⑹ if ((UINT32)flag & MNT_FORCE) { ret = CloseAll(index); if (ret != FS_SUCCESS) { goto OUT; } } ⑺ res = f_mount((FATFS *)NULL, target, 0); if (res != FR_OK) { errno = FatfsErrno(res); ret = FS_FAILURE; goto OUT; } if (g_fatfs[index].win != NULL) { ff_memfree(g_fatfs[index].win); } (void)memset_s(&g_fatfs[index], sizeof(FATFS), 0x0, sizeof(FATFS)); ret = FS_SUCCESS; OUT: FsUnlock(); return ret; }

      3.2 文件目錄操作接口

      文件目錄操作接口包含fatfs_mkdir、fatfs_unlink、fatfs_rmdir、fatfs_readdir、fatfs_closedir、fatfs_open、fatfs_close等等,會進一步調用FatFS的文件目錄操作接口進行封裝,代碼比較簡單,自行閱讀即可,部分代碼片段如下。

      ...... int fatfs_close(int fd) { FRESULT res; INT32 ret; ret = FsLock(); if (ret != 0) { errno = ret; return FS_FAILURE; } if (!IsValidFd(fd)) { FsUnlock(); errno = EBADF; return FS_FAILURE; } if (g_handle[fd].fil.obj.fs == NULL) { FsUnlock(); errno = ENOENT; return FS_FAILURE; } res = f_close(&g_handle[fd].fil); if (res != FR_OK) { PRINTK("FAT close err 0x%x!\r\n", res); FsUnlock(); errno = FatfsErrno(res); return FS_FAILURE; } #if !FF_FS_TINY if (g_handle[fd].fil.buf != NULL) { (void)ff_memfree(g_handle[fd].fil.buf); } #endif (void)memset_s(&g_handle[fd], sizeof(FatHandleStruct), 0x0, sizeof(FatHandleStruct)); if (g_fileNum > 0) { g_fileNum--; } FsUnlock(); return FS_SUCCESS; } ......

      鴻蒙輕內核M核源碼分析系列二一 03 文件系統FatFS(2)

      小結

      本文介紹了FatFS的結構體和全局變量,全局變量的操作接口,分析了下FatFS文件操作接口。時間倉促和能力關系,如有失誤,歡迎指正。感謝閱讀,如有任何問題、建議,都可以博客下留言給我,謝謝。

      參考資料

      HarmonyOS Device>文檔指南>基礎能力-FatFS

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:trello項目管理
      下一篇:WPS表格中怎么插入特殊符號?wps特殊符號插入方法
      相關文章
      久久久国产精品亚洲一区| 亚洲2022国产成人精品无码区| 亚洲图片校园春色| 久久亚洲高清综合| JLZZJLZZ亚洲乱熟无码| 亚洲欧美一区二区三区日产| 亚洲精品第一国产综合精品| 4444亚洲国产成人精品| 人人狠狠综合久久亚洲88| 亚洲成AV人片在线观看WWW| 亚洲av无码不卡| 亚洲2022国产成人精品无码区 | 亚洲色欲久久久综合网东京热| 噜噜噜亚洲色成人网站| 亚洲精品国产成人影院| 国产亚洲一区二区三区在线不卡| 亚洲乱亚洲乱少妇无码| 亚洲精品tv久久久久久久久久| 亚洲国产午夜福利在线播放| 国产偷国产偷亚洲高清日韩| 亚洲А∨精品天堂在线| 亚洲男人的天堂在线va拉文| 中文字幕精品亚洲无线码二区| 亚洲人成人一区二区三区| 亚洲AV日韩AV鸥美在线观看| 国产亚洲精品一品区99热| 亚洲AV人人澡人人爽人人夜夜| 久久亚洲精品无码AV红樱桃| 亚洲一区电影在线观看| 亚洲人成网亚洲欧洲无码| 亚洲av无码片vr一区二区三区| 亚洲av午夜国产精品无码中文字 | 亚洲aⅴ无码专区在线观看春色 | 亚洲精品白浆高清久久久久久| 亚洲宅男天堂在线观看无病毒| 精品亚洲综合在线第一区| 久久精品a亚洲国产v高清不卡| 亚洲第一成年网站大全亚洲| 亚洲AV无码无限在线观看不卡| 亚洲heyzo专区无码综合| 亚洲七七久久精品中文国产|