当前位置: 首页 > news >正文

鸿蒙轻内核M核源码分析系列二一 02 文件系统LittleFS

往期知识点记录:

  • 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
  • 持续更新中……

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;
}

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • AI为云游戏带来的革新及解决方案:深度技术剖析与未来展望
  • Android Framework(五)WMS-窗口显示流程——窗口布局与绘制显示
  • element UI学习使用(1)
  • Html、Css3动画效果
  • 1 MATLAB 绘图函数函数: plot
  • kvm 虚拟机命令行虚拟机操作、制作快照和恢复快照以及工作常用总结
  • 【Python爬虫】利用爬虫抓取双色球开奖号码,获取完整数据并通过随机森林和多层感知两种模型进行简单的预测
  • redis基本数据类型和常见命令
  • 工具使用记录-Tkinter
  • Leetcode 无重复字符的最长子串
  • slf4j依赖冲突处理
  • torchvision.transforms.ToPILImage()使用
  • MySQL 故障排查与性能优化指南
  • 韶音开放式耳机好用吗?南卡、韶音、Oladance、Cleer热门开放式耳机一周横评
  • 【Gateway】网关服务快速上手
  • CSS 专业技巧
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • Logstash 参考指南(目录)
  • opencv python Meanshift 和 Camshift
  • php的插入排序,通过双层for循环
  • Promise面试题,控制异步流程
  • SSH 免密登录
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 彻底搞懂浏览器Event-loop
  • 分类模型——Logistics Regression
  • 回顾2016
  • 简单数学运算程序(不定期更新)
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 智能合约开发环境搭建及Hello World合约
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • 容器镜像
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • #pragma data_seg 共享数据区(转)
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (7)摄像机和云台
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (vue)页面文件上传获取:action地址
  • (备份) esp32 GPIO
  • (轉貼) UML中文FAQ (OO) (UML)
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net 7 上传文件踩坑
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NET框架
  • .net生成的类,跨工程调用显示注释
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • @Autowired多个相同类型bean装配问题
  • @Controller和@RestController的区别?
  • @RequestBody与@ModelAttribute
  • @RunWith注解作用
  • @Transactional 参数详解
  • [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存...
  • [APIO2012] 派遣 dispatching