# 鴻蒙內核M核源碼分析系列二一 02 文件系統LittleFS

      網友投稿 862 2025-04-01

      鴻蒙輕內核M核源碼分析系列二一 02 文件系統LittleFS


      LittleFS是一個小型的Flash文件系統,它結合日志結構(log-structured)文件系統和COW(copy-on-write)文件系統的思想,以日志結構存儲元數據,以COW結構存儲數據。這種特殊的存儲方式,使LittleFS具有強大的掉電恢復能力(power-loss resilience)。分配COW數據塊時LittleFS采用了名為統計損耗均衡的動態損耗均衡算法,使Flash設備的壽命得到有效保障。同時LittleFS針對資源緊缺的小型設備進行設計,具有極其有限的ROM和RAM占用,并且所有RAM的使用都通過一個可配置的固定大小緩沖區進行分配,不會隨文件系統的擴大占據更多的系統資源。當在一個資源非常緊缺的小型設備上,尋找一個具有掉電恢復能力并支持損耗均衡的Flash文件系統時,LittleFS是一個比較好的選擇。本文先介紹下LFS文件系統結構體的結構體和全局變量,然后分析下LFS文件操作接口。文中所涉及的源碼,均可以在開源站點https://gitee.com/openharmony/kernel_liteos_m 獲取。

      1、LFS文件系統結構體介紹

      會分2部分來介紹結構體部分,先介紹LittleFS文件系統的結構體,然后介紹LiteOS-M內核中提供的和LittleFS相關的一些結構體。

      1.1 LittleFS的枚舉結構體

      在openharmony/third_party/littlefs/lfs.h頭文件中定義LittleFS的枚舉、結構體,我們先簡單了解下,后文會使用到的。

      枚舉lfs_type定義文件類型,了解下普通文件LFS_TYPE_REG和目錄LFS_TYPE_DIR即可。枚舉lfs_open_flags定義文件系統的打開標簽屬性信息,需要熟悉常用的只讀LFS_O_RDONLY、只寫LFS_O_WRONLY、讀寫LFS_O_RDWR等等。

      // File types enum lfs_type { // file types LFS_TYPE_REG = 0x001, LFS_TYPE_DIR = 0x002, // internally used types LFS_TYPE_SPLICE = 0x400, LFS_TYPE_NAME = 0x000, LFS_TYPE_STRUCT = 0x200, LFS_TYPE_USERATTR = 0x300, LFS_TYPE_FROM = 0x100, LFS_TYPE_TAIL = 0x600, LFS_TYPE_GLOBALS = 0x700, LFS_TYPE_CRC = 0x500, // internally used type specializations LFS_TYPE_CREATE = 0x401, LFS_TYPE_DELETE = 0x4ff, LFS_TYPE_SUPERBLOCK = 0x0ff, LFS_TYPE_DIRSTRUCT = 0x200, LFS_TYPE_CTZSTRUCT = 0x202, LFS_TYPE_INLINESTRUCT = 0x201, LFS_TYPE_SOFTTAIL = 0x600, LFS_TYPE_HARDTAIL = 0x601, LFS_TYPE_MOVESTATE = 0x7ff, // internal chip sources LFS_FROM_NOOP = 0x000, LFS_FROM_MOVE = 0x101, LFS_FROM_USERATTRS = 0x102, }; // File open flags enum lfs_open_flags { // open flags LFS_O_RDONLY = 1, // Open a file as read only #ifndef LFS_READONLY LFS_O_WRONLY = 2, // Open a file as write only LFS_O_RDWR = 3, // Open a file as read and write LFS_O_CREAT = 0x0100, // Create a file if it does not exist LFS_O_EXCL = 0x0200, // Fail if a file already exists LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size LFS_O_APPEND = 0x0800, // Move to end of file on every write #endif // internally used flags #ifndef LFS_READONLY LFS_F_DIRTY = 0x010000, // File does not match storage LFS_F_WRITING = 0x020000, // File has been written since last flush #endif LFS_F_READING = 0x040000, // File has been read since last flush #ifndef LFS_READONLY LFS_F_ERRED = 0x080000, // An error occurred during write #endif LFS_F_INLINE = 0x100000, // Currently inlined in directory entry };

      結構體lfs_t是littlefs文件系統類型結構體,lfs文件系統操作接口的第一個參數一般為這個結構體。成員變量struct lfs_config *cfg下文會涉及,其他成員變量可以暫不了解。

      // The littlefs filesystem type typedef struct lfs { lfs_cache_t rcache; lfs_cache_t pcache; lfs_block_t root[2]; struct lfs_mlist { struct lfs_mlist *next; uint16_t id; uint8_t type; lfs_mdir_t m; } *mlist; uint32_t seed; lfs_gstate_t gstate; lfs_gstate_t gdisk; lfs_gstate_t gdelta; struct lfs_free { lfs_block_t off; lfs_block_t size; lfs_block_t i; lfs_block_t ack; uint32_t *buffer; } free; const struct lfs_config *cfg; lfs_size_t name_max; lfs_size_t file_max; lfs_size_t attr_max; #ifdef LFS_MIGRATE struct lfs1 *lfs1; #endif } lfs_t;

      結構體lfs_file_t、lfs_dir_t分別是littlefs的文件和目錄類型結構體,暫不需要關心成員變量細節,知道結構體的用途即可。

      // littlefs directory type typedef struct lfs_dir { struct lfs_dir *next; uint16_t id; uint8_t type; lfs_mdir_t m; lfs_off_t pos; lfs_block_t head[2]; } lfs_dir_t; // littlefs file type typedef struct lfs_file { struct lfs_file *next; uint16_t id; uint8_t type; lfs_mdir_t m; struct lfs_ctz { lfs_block_t head; lfs_size_t size; } ctz; uint32_t flags; lfs_off_t pos; lfs_block_t block; lfs_off_t off; lfs_cache_t cache; const struct lfs_file_config *cfg; } lfs_file_t;

      結構體lfs_config用于提供初始化littlefs文件系統的一些配置。其中.read,.prog,.erase,.sync分別對應該硬件平臺上的底層的讀寫\擦除\同步等接口。

      read_size 每次讀取的字節數,可以比物理讀單元大以改善性能,這個數值決定了讀緩存的大小,但值太大會帶來更多的內存消耗。

      prog_size 每次寫入的字節數,可以比物理寫單元大以改善性能,這個數值決定了寫緩存的大小,必須是read_size的整數倍,但值太大會帶來更多的內存消耗。

      block_size 每個擦除塊的字節數,可以比物理擦除單元大,但此數值應盡可能小因為每個文件至少會占用一個塊。必須是prog_size的整數倍。

      block_count 可以被擦除的塊數量,這取決于塊設備的容量及擦除塊的大小。

      // Configuration provided during initialization of the littlefs struct lfs_config { // Opaque user provided context that can be used to pass // information to the block device operations void *context; int (*read)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); int (*prog)(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size); int (*erase)(const struct lfs_config *c, lfs_block_t block); int (*sync)(const struct lfs_config *c); #ifdef LFS_THREADSAFE int (*lock)(const struct lfs_config *c); int (*unlock)(const struct lfs_config *c); #endif lfs_size_t read_size; lfs_size_t prog_size; lfs_size_t block_size; lfs_size_t block_count; int32_t block_cycles; lfs_size_t cache_size; lfs_size_t lookahead_size; void *read_buffer; void *prog_buffer; void *lookahead_buffer; lfs_size_t name_max; lfs_size_t file_max; lfs_size_t attr_max; lfs_size_t metadata_max; };

      結構體lfs_info用于維護文件信息,包含文件類型,大小和文件名信息。

      // File info structure struct lfs_info { // Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR uint8_t type; // Size of the file, only valid for REG files. Limited to 32-bits. lfs_size_t size; // Name of the file stored as a null-terminated string. Limited to // LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to // reduce RAM. LFS_NAME_MAX is stored in superblock and must be // respected by other littlefs drivers. char name[LFS_NAME_MAX+1]; };

      1.2 LiteOS-M LittleFS的結構體

      我們來看下在文件components\fs\littlefs\lfs_api.h里定義的幾個結構體。結構體LittleFsHandleStruct維護文件相關的信息,該結構體的成員包含是否使用,文件路徑和lfs文件系統類型結構體lfs_t *lfsHandle和文件類型結構體lfs_file_t file。類似的,結構體FileDirInfo維護目錄相關的信息,該結構體成員包含包含是否使用,目錄名稱和lfs文件系統類型結構體lfs_t *lfsHandle和目錄類型結構體lfs_dir_t dir。另外一個結構體FileOpInfo維護文件操作信息。

      typedef struct { uint8_t useFlag; const char *pathName; lfs_t *lfsHandle; lfs_file_t file; } LittleFsHandleStruct; struct FileOpInfo { uint8_t useFlag; const struct FileOps *fsVops; char *dirName; lfs_t lfsInfo; }; typedef struct { uint8_t useFlag; char *dirName; lfs_t *lfsHandle; lfs_dir_t dir; } FileDirInfo;

      2、LiteOS-M LittleFS的重要全局變量及操作

      了解下文件components\fs\littlefs\lfs_api.c定義的常用全局變量。⑴處的g_lfsDir數組維護目錄信息,默認支持的目錄數目為LFS_MAX_OPEN_DIRS,等于10。⑵處的g_fsOp數組維護針對每個掛載點的文件操作信息,默認掛載點數目LOSCFG_LFS_MAX_MOUNT_SIZE為3個。⑶處的g_handle數組維護文件信息,默認支持文件的數量LITTLE_FS_MAX_OPEN_FILES為100個。⑷處開始的struct dirent g_nameValue是目錄項結構體變量,用于函數LfsReaddir();pthread_mutex_t g_FslocalMutex是互斥鎖變量;g_littlefsMntName是掛載點名稱數組。⑸處開始的掛載操作變量g_lfsMnt、文件操作操作全局變量g_lfsFops在虛擬文件系統中被使用。

      ⑴ FileDirInfo g_lfsDir[LFS_MAX_OPEN_DIRS] = {0}; ⑵ struct FileOpInfo g_fsOp[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0}; ⑶ static LittleFsHandleStruct g_handle[LITTLE_FS_MAX_OPEN_FILES] = {0}; ⑷ struct dirent g_nameValue; static pthread_mutex_t g_FslocalMutex = PTHREAD_MUTEX_INITIALIZER; static const char *g_littlefsMntName[LOSCFG_LFS_MAX_MOUNT_SIZE] = {"/a", "/b", "/c"}; ...... ⑸ const struct MountOps g_lfsMnt = { .Mount = LfsMount, .Umount = LfsUmount, }; const struct FileOps g_lfsFops = { .Mkdir = LfsMkdir, .Unlink = LfsUnlink, .Rmdir = LfsRmdir, .Opendir = LfsOpendir, .Readdir = LfsReaddir, .Closedir = LfsClosedir, .Open = LfsOpen, .Close = LfsClose, .Write = LfsWrite, .Read = LfsRead, .Seek = LfsSeek, .Rename = LfsRename, .Getattr = LfsStat, .Fsync = LfsFsync, .Fstat = LfsFstat, };

      下文繼續介紹下和這些變量相關的內部操作接口。

      2.1 目錄信息數組操作

      GetFreeDir()設置目錄信息數組元素信息。參數dirName為目錄名稱。遍歷目錄信息數組,遍歷到第一個未使用的元素標記其為已使用狀態,設置目錄名稱,返回目錄信息元素指針地址。如果遍歷失敗,返回NULL。函數FreeDirInfo()為函數GetFreeDir()的反向操作,根據目錄名稱設置對應的數組元素為未使用狀態,并把GetFreeDir設置為NULL。

      函數CheckDirIsOpen()用于檢測目錄是否已經打開。如果目錄信息數組中記錄著對應的目錄信息,則標志著該目錄已經打開。

      FileDirInfo *GetFreeDir(const char *dirName) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { if (g_lfsDir[i].useFlag == 0) { g_lfsDir[i].useFlag = 1; g_lfsDir[i].dirName = strdup(dirName); pthread_mutex_unlock(&g_FslocalMutex); return &(g_lfsDir[i]); } } pthread_mutex_unlock(&g_FslocalMutex); return NULL; } void FreeDirInfo(const char *dirName) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { if (g_lfsDir[i].useFlag == 1 && strcmp(g_lfsDir[i].dirName, dirName) == 0) { g_lfsDir[i].useFlag = 0; if (g_lfsDir[i].dirName) { free(g_lfsDir[i].dirName); g_lfsDir[i].dirName = NULL; } pthread_mutex_unlock(&g_FslocalMutex); } } pthread_mutex_unlock(&g_FslocalMutex); } BOOL CheckDirIsOpen(const char *dirName) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LFS_MAX_OPEN_DIRS; i++) { if (g_lfsDir[i].useFlag == 1) { if (strcmp(g_lfsDir[i].dirName, dirName) == 0) { pthread_mutex_unlock(&g_FslocalMutex); return TRUE; } } } pthread_mutex_unlock(&g_FslocalMutex); return FALSE; }

      2.2 文件信息數組操作

      函數LfsAllocFd()設置文件信息數組元素信息。參數fileName為文件路徑信息,傳出參數fd為文件描述符即數組索引。遍歷文件信息數組,遍歷到第一個未使用的元素標記其為已使用狀態,設置文件路徑信息,把數組索引賦值給文件描述符fd,返回文件信息元素指針地址。如果遍歷失敗,返回NULL。函數LfsFreeFd()為函數LfsAllocFd()的反向操作,根據文件描述符設置對應的數組元素為未使用狀態,并把路徑信息等設置為NULL。

      函數CheckFileIsOpen()用于檢測文件是否已經打開,文件如果打開過,則表示獲取過該文件的文件描述符,根據對應的fd文件描述符,可以對文件進行更多的操作。如果文件信息數組中記錄著對應的文件路徑信息,則標志著該文件已經打開。函數LfsFdIsValid()用于判斷文件描述符是否有效。

      LittleFsHandleStruct *LfsAllocFd(const char *fileName, int *fd) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LITTLE_FS_MAX_OPEN_FILES; i++) { if (g_handle[i].useFlag == 0) { *fd = i; g_handle[i].useFlag = 1; g_handle[i].pathName = strdup(fileName); pthread_mutex_unlock(&g_FslocalMutex); return &(g_handle[i]); } } pthread_mutex_unlock(&g_FslocalMutex); *fd = INVALID_FD; return NULL; } static void LfsFreeFd(int fd) { pthread_mutex_lock(&g_FslocalMutex); g_handle[fd].useFlag = 0; if (g_handle[fd].pathName != NULL) { free((void *)g_handle[fd].pathName); g_handle[fd].pathName = NULL; } if (g_handle[fd].lfsHandle != NULL) { g_handle[fd].lfsHandle = NULL; } pthread_mutex_unlock(&g_FslocalMutex); } BOOL CheckFileIsOpen(const char *fileName) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LITTLE_FS_MAX_OPEN_FILES; i++) { if (g_handle[i].useFlag == 1) { if (strcmp(g_handle[i].pathName, fileName) == 0) { pthread_mutex_unlock(&g_FslocalMutex); return TRUE; } } } pthread_mutex_unlock(&g_FslocalMutex); return FALSE; } static BOOL LfsFdIsValid(int fd) { if (fd >= LITTLE_FS_MAX_OPEN_FILES || fd < 0) { return FALSE; } if (g_handle[fd].lfsHandle == NULL) { return FALSE; } return TRUE; }

      2.3 掛載點文件操作信息相關操作

      函數AllocMountRes()用于設置掛載點文件操作信息。參數target為掛載點名稱,參數fileOps為文件操作信息。遍歷每個掛載點,如果遍歷到的掛載點未使用,并且掛載點名稱相等,則設置其使用標記為已使用,設置目錄名稱,設置文件操作信息,然后返回文件操作信息指針。如果沒有遍歷到,返回NULL。掛載點數組g_littlefsMntName的元素默認為/a,/b,/c等,可以使用函數SetDefaultMountPath()設置指定位置的掛載點名稱。

      struct FileOpInfo *AllocMountRes(const char* target, const struct FileOps *fileOps) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { if (g_fsOp[i].useFlag == 0 && strcmp(target, g_littlefsMntName[i]) == 0) { g_fsOp[i].useFlag = 1; g_fsOp[i].fsVops = fileOps; g_fsOp[i].dirName = strdup(target); pthread_mutex_unlock(&g_FslocalMutex); return &(g_fsOp[i]); } } pthread_mutex_unlock(&g_FslocalMutex); return NULL; } int SetDefaultMountPath(int pathNameIndex, const char* target) { if (pathNameIndex >= LOSCFG_LFS_MAX_MOUNT_SIZE) { return VFS_ERROR; } pthread_mutex_lock(&g_FslocalMutex); g_littlefsMntName[pathNameIndex] = strdup(target); pthread_mutex_unlock(&g_FslocalMutex); return VFS_OK; }

      函數GetMountRes()用于獲取給定掛載點在掛載點文件操作信息數組中的索引值。參數target為掛載點名稱,參數mountIndex用于輸出文件操作信息數組索引值。遍歷每個掛載點,如果遍歷到的掛載點已使用,并且掛載點名稱相等,則返回相應的數組索引,否則返回NULL。

      struct FileOpInfo *GetMountRes(const char *target, int *mountIndex) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { if (g_fsOp[i].useFlag == 1) { if (g_fsOp[i].dirName && strcmp(target, g_fsOp[i].dirName) == 0) { *mountIndex = i; pthread_mutex_unlock(&g_FslocalMutex); return &(g_fsOp[i]); } } } pthread_mutex_unlock(&g_FslocalMutex); return NULL; }

      函數FreeMountResByIndex()屬于函數AllocMountRes()的反向操作,用于釋放掛載點文件操作信息。傳入參數mountIndex對應的文件操作信息標記為未使用狀態,釋放掛載點名稱占用的內存。函數FreeMountRes()實現的功能一樣,傳入參數為掛載點名稱。遍歷每一個掛載點,如果存在和傳入參數相同的掛載點,則進行釋放。

      int FreeMountResByIndex(int mountIndex) { if (mountIndex < 0 || mountIndex >= LOSCFG_LFS_MAX_MOUNT_SIZE) { return VFS_ERROR; } pthread_mutex_lock(&g_FslocalMutex); if (g_fsOp[mountIndex].useFlag == 1 && g_fsOp[mountIndex].dirName != NULL) { g_fsOp[mountIndex].useFlag = 0; free(g_fsOp[mountIndex].dirName); g_fsOp[mountIndex].dirName = NULL; } pthread_mutex_unlock(&g_FslocalMutex); return VFS_OK; } int FreeMountRes(const char *target) { pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { if (g_fsOp[i].useFlag == 1) { if (g_fsOp[i].dirName && strcmp(target, g_fsOp[i].dirName) == 0) { g_fsOp[i].useFlag = 0; free(g_fsOp[i].dirName); g_fsOp[i].dirName = NULL; pthread_mutex_unlock(&g_FslocalMutex); return VFS_OK; } } } pthread_mutex_unlock(&g_FslocalMutex); return VFS_ERROR; }

      2.4 路徑是否已掛載CheckPathIsMounted

      函數CheckPathIsMounted()用于檢查給定的路徑是否已經掛載,如果掛載上把對應掛載點的文件操作信息由參數struct FileOpInfo **fileOpInfo輸出。⑴處先獲取路徑的第一級目錄的長度。⑵處遍歷每一個掛載點的文件操作數組,如果文件操作處于使用狀態,則執行⑶比對相應的掛載點名稱和路徑的第一級目錄名稱是否相等。如果相等,則輸出文件操作信息,并返回TRUE。否則返回FALSE。

      int GetFirstLevelPathLen(const char *pathName) { int len = 1; for (int i = 1; i < strlen(pathName) + 1; i++) { if (pathName[i] == '/') { break; } len++; } return len; } BOOL CheckPathIsMounted(const char *pathName, struct FileOpInfo **fileOpInfo) { char tmpName[LITTLEFS_MAX_LFN_LEN] = {0}; ⑴ int len = GetFirstLevelPathLen(pathName); pthread_mutex_lock(&g_FslocalMutex); for (int i = 0; i < LOSCFG_LFS_MAX_MOUNT_SIZE; i++) { ⑵ if (g_fsOp[i].useFlag == 1) { (void)strncpy_s(tmpName, LITTLEFS_MAX_LFN_LEN, pathName, len); ⑶ if (strcmp(tmpName, g_fsOp[i].dirName) == 0) { *fileOpInfo = &(g_fsOp[i]); pthread_mutex_unlock(&g_FslocalMutex); return TRUE; } } } pthread_mutex_unlock(&g_FslocalMutex); return FALSE; }

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

      快速記錄下各個操作接口,對每個接口的用途用法不再描述。可以參考之前的系列文章,《鴻蒙輕內核M核源碼分析系列十九 Musl LibC》中介紹了相關的接口,那些接口會調用VFS文件系統中操作接口,然后進一步調用LFS文件操作接口。

      3.1 掛載LfsMount和卸載LfsUmounts操作

      掛載卸載操作包含LfsMount、LfsUmounts等2個操作。對于函數LfsMount(),需要注意下參數const void *data,這個需要是struct lfs_config指針類型變量。⑴處在掛載文件系統之前,對輸入參數進行檢測。⑵處判斷是否已經掛載,不允許重復掛載。⑶處設置掛載點信息,⑷處調用LFS的函數實現掛載,如果掛載失敗,則執行⑸嘗試格式化,然后重新掛載。

      對于函數LfsUmount(),⑹處根據掛載點獲取文件操作信息和掛載點索引值。⑺處調用LFS函數實現卸載,然后執行⑻釋放掛載點文件操作信息。

      int LfsMount(const char *source, const char *target, const char *fileSystemType, unsigned long mountflags, const void *data) { int ret; struct FileOpInfo *fileOpInfo = NULL; ⑴ if (target == NULL || fileSystemType == NULL || data == NULL) { errno = EFAULT; ret = VFS_ERROR; goto errout; } if (strcmp(fileSystemType, "littlefs") != 0) { errno = ENODEV; ret = VFS_ERROR; goto errout; } ⑵ if (CheckPathIsMounted(target, &fileOpInfo)) { errno = EBUSY; ret = VFS_ERROR; goto errout; } // select free mount resource ⑶ fileOpInfo = AllocMountRes(target, &g_lfsFops); if (fileOpInfo == NULL) { errno = ENODEV; ret = VFS_ERROR; goto errout; } ⑷ ret = lfs_mount(&(fileOpInfo->lfsInfo), (struct lfs_config*)data); if (ret != 0) { ⑸ ret = lfs_format(&(fileOpInfo->lfsInfo), (struct lfs_config*)data); if (ret == 0) { ret = lfs_mount(&(fileOpInfo->lfsInfo), (struct lfs_config*)data); } } if (ret != 0) { errno = LittlefsErrno(ret); ret = VFS_ERROR; } errout: return ret; } int LfsUmount(const char *target) { int ret; int mountIndex = -1; struct FileOpInfo *fileOpInfo = NULL; if (target == NULL) { errno = EFAULT; return VFS_ERROR; } ⑹ fileOpInfo = GetMountRes(target, &mountIndex); if (fileOpInfo == NULL) { errno = ENOENT; return VFS_ERROR; } ⑺ ret = lfs_unmount(&(fileOpInfo->lfsInfo)); if (ret != 0) { errno = LittlefsErrno(ret); ret = VFS_ERROR; } ⑻ (void)FreeMountResByIndex(mountIndex); return ret; }

      3.2 文件目錄操作接口

      文件目錄操作接口包含LfsMkdir、LfsUnlink、LfsRmdir、LfsReaddir、LfsClosedir、LfsOpen、LfsClose等等,會進一步調用LFS的文件目錄操作接口進行封裝,代碼比較簡單,自行閱讀即可,部分代碼片段如下。

      ...... int LfsUnlink(const char *fileName) { int ret; struct FileOpInfo *fileOpInfo = NULL; if (fileName == NULL) { errno = EFAULT; return VFS_ERROR; } if (CheckPathIsMounted(fileName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { errno = ENOENT; return VFS_ERROR; } ret = lfs_remove(&(fileOpInfo->lfsInfo), fileName); if (ret != 0) { errno = LittlefsErrno(ret); ret = VFS_ERROR; } return ret; } int LfsMkdir(const char *dirName, mode_t mode) { int ret; struct FileOpInfo *fileOpInfo = NULL; if (dirName == NULL) { errno = EFAULT; return VFS_ERROR; } if (CheckPathIsMounted(dirName, &fileOpInfo) == FALSE || fileOpInfo == NULL) { errno = ENOENT; return VFS_ERROR; } ret = lfs_mkdir(&(fileOpInfo->lfsInfo), dirName); if (ret != 0) { errno = LittlefsErrno(ret); ret = VFS_ERROR; } return ret; } ......

      # 鴻蒙輕內核M核源碼分析系列二一 02 文件系統LittleFS

      小結

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

      參考資料

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

      IoT 輕量級操作系統 LiteOS

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

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

      上一篇:C# 4 中的 Dynamic 關鍵字
      下一篇:如何找到wps里面的文件格式關聯(怎么取消wps和office文件格式的關聯)
      相關文章
      亚洲日韩aⅴ在线视频| 亚洲真人日本在线| 在线观看国产一区亚洲bd| 最新国产精品亚洲| 亚洲最大免费视频网| 77777_亚洲午夜久久多人| 国产av天堂亚洲国产av天堂 | 在线看亚洲十八禁网站| 亚洲日韩AV一区二区三区中文| 2020年亚洲天天爽天天噜| 亚洲成无码人在线观看| 久久精品国产亚洲AV麻豆网站| 无码专区—VA亚洲V天堂| 亚洲av鲁丝一区二区三区| 亚洲网址在线观看你懂的| 亚洲国产精品不卡在线电影| 日木av无码专区亚洲av毛片| 97se亚洲综合在线| 亚洲国产av高清无码| 亚洲国产综合精品中文第一| 亚洲熟妇av午夜无码不卡| 亚洲国产成人手机在线观看| 国产成人精品亚洲一区| 亚洲一级黄色视频| 伊人久久大香线蕉亚洲五月天| 亚洲综合在线另类色区奇米| 亚洲综合色自拍一区| 国产AV无码专区亚洲AVJULIA| 亚洲国产成人久久综合碰碰动漫3d| 97久久精品亚洲中文字幕无码 | 亚洲美女高清一区二区三区| 久久亚洲国产精品五月天婷| 国产亚洲综合网曝门系列| 亚洲国产精品久久久久网站| 亚洲性色高清完整版在线观看| 亚洲AV成人无码天堂| 亚洲成a∨人片在无码2023| 亚洲国产人成中文幕一级二级| 亚洲一区二区三区在线观看精品中文| 国产成人亚洲精品青草天美| 麻豆亚洲AV永久无码精品久久|