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 typesLFS_TYPE_REG = 0x001,LFS_TYPE_DIR = 0x002,// internally used typesLFS_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 specializationsLFS_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 sourcesLFS_FROM_NOOP = 0x000,LFS_FROM_MOVE = 0x101,LFS_FROM_USERATTRS = 0x102,
};// File open flags
enum lfs_open_flags {// open flagsLFS_O_RDONLY = 1, // Open a file as read only
#ifndef LFS_READONLYLFS_O_WRONLY = 2, // Open a file as write onlyLFS_O_RDWR = 3, // Open a file as read and writeLFS_O_CREAT = 0x0100, // Create a file if it does not existLFS_O_EXCL = 0x0200, // Fail if a file already existsLFS_O_TRUNC = 0x0400, // Truncate the existing file to zero sizeLFS_O_APPEND = 0x0800, // Move to end of file on every write
#endif// internally used flags
#ifndef LFS_READONLYLFS_F_DIRTY = 0x010000, // File does not match storageLFS_F_WRITING = 0x020000, // File has been written since last flush
#endifLFS_F_READING = 0x040000, // File has been read since last flush
#ifndef LFS_READONLYLFS_F_ERRED = 0x080000, // An error occurred during write
#endifLFS_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_MIGRATEstruct 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 operationsvoid *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_THREADSAFEint (*lock)(const struct lfs_config *c);int (*unlock)(const struct lfs_config *c);
#endiflfs_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_DIRuint8_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;
}
如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:
OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy
《OpenHarmony源码解析》:https://qr18.cn/CgxrRy
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
系统架构分析:https://qr18.cn/CgxrRy
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……
OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy
OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy
写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:
https://qr21.cn/FV7h05