鸿蒙轻内核M核源码分析系列二一 02 文件系统LittleFS
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
相关文章:

鸿蒙轻内核M核源码分析系列二一 02 文件系统LittleFS
1、LFS文件系统结构体介绍 会分2部分来介绍结构体部分,先介绍LittleFS文件系统的结构体,然后介绍LiteOS-M内核中提供的和LittleFS相关的一些结构体。 1.1 LittleFS的枚举结构体 在openharmony/third_party/littlefs/lfs.h头文件中定义LittleFS的枚举、…...

【ARMv8/ARMv9 硬件加速系列 3 -- SVE 指令语法及编译参数详细介绍】
文章目录 SVE 汇编语法SVE 单通道谓词SVE 测试代码 SVE 软件和库支持SVE 编译参数配置-marcharmv8-alseprofilememtagsve2-aessve2-bitpermcryptosve2sve2-sha3sve2-sm4 SVE 汇编语法 在介绍 SVE 汇编指令语法之前,先介绍下如何判断自己所使用的芯片是否实现了SVE功…...

Java版+ SaaS应用+接口技术RESTful API 技术开发的智慧医院HIS系统源码 专注医院管理系统研发 支持二开
Java版 SaaS应用接口技术RESTful API WebSocket WebService技术开发的智慧医院HIS系统源码 专注医院管理系统研发 支持二开 医院住院管理系统(Hospital Information System简称HIS)是一门医学、信息、管理、计算机等多种学科为一体的边缘科学ÿ…...

工业机器人远程运维,增强智慧工厂运营管理
1、需求背景 随着工业自动化技术的普及和工业机器人应用的增加,制造业对于生产线稳定性和效率的要求不断提高。然而,传统的现场监控方式存在着地理位置限制、实时监控难度大以及诊断能力有限等问题,迫切需要一种更具灵活性和效率的监控方式。…...

理解Python的元类
1.type()函数 type 函数是一个内置函数,用来获取一个对象的类型。它可以接受一个参数,返回这个参数的数据类型。type也可以用来创建类,type就是元类 x333 list["ab"] tuple (1, "a", True, 3.14) dict {name: Alice,…...

web前端黑马下载:探索学习资源的海洋
web前端黑马下载:探索学习资源的海洋 在数字化时代,Web前端技术日益成为互联网行业的核心驱动力。为了跟上这一趋势,众多学习者纷纷投身于Web前端的学习之中。而在这个过程中,“黑马”作为一个备受瞩目的品牌,其Web前…...

最新版jd-gui下载
对于java开发的工程师来说,jd-gui应该是经常会用到的工具了 官网的jd-gui目前只支持到JAVA13,更新版本JAVA编译出来的JAR包就反编译不出来了 此版本支持到了JAVA23 如果需要win以外的其他版本,可以查看我的其他上传 如果不想花积分&#…...

(051)FPGA时钟--->(001)时钟介绍
(001)时钟介绍 1 目录 (a)FPGA简介 (b)Verilog简介 (c)时钟简介 (d)时钟介绍 (e)结束 1 FPGA简介 (a)FPGA(Field Programmable Gate Array)是在PAL (可编程阵列逻辑)、GAL(通用阵列逻辑)等可编程器件的基础上进一步发展的产物。它是作为专用集成电…...

Java程序员英语单词通关:
Java程序员英语单词通关: abstract - 抽象的 boolean - 布尔值 break - 打断 byte - 字节 case - 情况,实例 catch - 捕获 char - 字符 class - 类 continue - 继续 default - 默认,通常 do - 做,运行 double - 双精度…...

数据库开发-Mysql03
目录 1. 多表查询 1.1 概述 1.1.1 数据准备 1.1.2 介绍 1.1.3 分类 1.2 内连接 1.3 外连接 1.4 子查询 1.4.1 介绍 1.4.2 标量子查询 1.4.3 列子查询 1.4.4 行子查询 1.4.5 表子查询 1.5 案例 2. 事务 2.1 介绍 2.2 操作 2.3 四大特性 3. 索引 3.1 介绍 3…...

0-1 背包问题(动态规划 查询背包元素)
描述 给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,问如何选择装入背包的物品,使得装入背包的物品的总价值最大? 在选择装入背包的物品时,对每种物品i只能有两种选择,装入或者不装入…...

elasticsearch快照生成与恢复
Elasticsearch快照生成与恢复的场景主要涉及到数据的备份与恢复需求。当需要对Elasticsearch集群中的数据进行备份,或者在数据丢失、损坏等情况下需要恢复数据时,就可以使用快照功能。 快照生成的方法通常包括以下步骤: 1、创建一个快照仓库…...

178.二叉树:最大二叉树(力扣)
代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…...

跨境电商中的IP隔离是什么?怎么做?
一、IP地址隔离的概念和原理 当我们谈论 IP 地址隔离时,我们实际上是在讨论一种网络安全策略,旨在通过技术手段将网络划分为不同的区域或子网,每个区域或子网都有自己独特的 IP 地址范围。这种划分使网络管理员可以更精细地控制哪些设备或用…...

【C++】stack、queue和deque的使用
💗个人主页💗 ⭐个人专栏——C学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 导读 一、stack 1. stack介绍 2. stack使用 二、queue 1. queue介绍 2. queue使用 三、deque 1. deque介绍 2. deque的…...

通过SSH远程登录华为设备
01 进入系统编辑视图 system-view Enter system view, return user view with return command. 02 创建本地RSA密钥对 [HUAWEI]rsa local-key-pair creat The key name will be:HUAWEI_Host The range of public key size is (2048 ~ 2048). NOTE: Key pair generation will ta…...

算法day27
第一题 515. 在每个树行中找最大值 首先是遍历每层的节点,将每一层最大值的节点的值保留下来,最后将所有层的最大值的表返回;具体的遍历每层节点的过程如上一篇故事; 综上所述,代码如下: /*** Definition …...

记录一次CTF图片拼图安装工具montage+gaps成功步骤以及踩坑全过程
安装图片拼接工具montage: 1.安装 使用pip install montage无法安装montage工具的师傅可以尝试下面的方法 #Debian apt-get install graphicsmagick-imagemagick-compat#Ubuntu apt-get install graphicsmagick-imagemagick-compat#Alpine apk add imagemagick6#…...

深入剖析人才管理的关键要素:“选、用、育、留”四大核心要素
在当今这个日新月异的商业时代,企业的成功不再仅仅取决于资金、技术或市场策略,而更多地依赖于企业所拥有的人才资源。有效的人才管理策略,尤其是“选、用、育、留”四大核心要素,已成为推动企业持续发展的关键。 一、选ÿ…...

【C++】类的默认成员函数
类的默认成员函数 类的六个默认成员函数构造函数构造函数的概念构造函数的特性 析构函数析构函数的概念析构函数的特性 构造函数与析构函数的调用顺序拷贝构造拷贝构造的概念拷贝构造的特性赋值运算符重载运算符重载赋值运算符重载前置与后置重载输入输出流重载 const修饰成员实…...

归并排序!
归并排序 https://articles.zsxq.com/id_g23e5o3lg87e.html 目录 归并排序算法思想命名由来算法描述sortList函数mergeSort函数 源代码 算法思想 通过将当前乱序的数组分成两个部分,分别进行「递归调用」,利用两个指针将数据元素以此比较,选…...

深入探讨:Spring与MyBatis中的连接池与缓存机制
深入探讨:Spring与MyBatis中的连接池与缓存机制 引言 在现代应用程序开发中,性能优化是一个永恒的话题。而在企业级Java应用开发中,Spring和MyBatis是两种非常流行的框架,它们的连接池和缓存机制对应用程序的性能有着至关重要的…...

[C#]使用C#部署yolov10的目标检测tensorrt模型
【测试通过环境】 win10 x64vs2019 cuda11.7cudnn8.8.0 TensorRT-8.6.1.6 opencvsharp4.9.0 .NET Framework4.7.2 NVIDIA GeForce RTX 2070 Super cuda和tensorrt版本和上述环境版本不一样的需要重新编译TensorRtExtern.dll,TensorRtExtern源码地址:T…...

Linux CFS 调度器 (1):概述
文章目录 1. 前言2. CFS 调度器2.1 概述2.2 一些实现细节2.3 运行队列:红黑树2.4 一些特征2.5 调度策略2.6 调度器类别2.7 扩展:组调度 3. 参考资料 1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失ÿ…...

HBase中Master初始化错误~
ERROR:org.apache.hadoop.hbase.PleaseHoldException:Master is initializing 1、停止HBase运行 2、启动zookeeper中的zkCli.sh服务 ./zookeeper/bin/zkCli.sh 3、执行完毕显示以下结果,删除habse文件夹 4、重新启动HBase即可。...

Hive on Spark版本兼容性
Hive on Spark仅在特定版本的Spark上进行测试,因此给定版本的Hive只能保证与特定版本的Spark一起工作。其他版本的Spark可能与给定版本的Hive一起工作,但不能保证。以下是Hive版本及其对应的Spark版本列表: 详情参考官方文档:http…...

grep命令知多少
引言 1. grep命令的重要性 在Linux系统中,grep是一个不可或缺的文本处理工具,它允许用户快速搜索文件中的文本模式。这个命令的名称来源于Global Regular Expression Print,即全局正则表达式打印,它源自UNIX早期的ed文本编辑器。…...

[java]windows和linux下jdk1.8安装包所有版本系列下载地址汇总
【windows jdk1.9系列下载地址】 序号java版本下载地址1java-jdk9-jdk-9.0.1-windows-x64-bin.zip点我下载 【windows jdk1.8系列下载地址】 序号java版本下载地址1java-jdk1.8-jdk-8u202-windows-x64.zip点我下载2java-jdk1.8-jdk-8u201-windows-x64.zip点我下载3java-jdk1…...

Electron+Vue开源软件:洛雪音乐助手V2.8畅享海量免费歌曲
洛雪音乐助手是一款功能全面且完全免费的开源音乐软件,支持在Windows、Android和iOS平台上使用。 平台支持: 桌面版:采用Electron Vue技术栈开发,支持Windows 7及以上版本、Mac OS和Linux,具有广泛的用户群体覆盖。 …...

CAPL通过addTimeToMeasurementStartTime或者getLocalTime获取本地时间
文章目录 getLocalTimeaddTimeToMeasurementStartTimegetLocalTime long tm[9]; getLocalTime(tm); // now tm contains the following entries: // tm[0] = 3; (seconds) // tm[1] = 51; (minutes) // tm[2] = 16; (hours)...