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

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

小结

本文介绍了LFS的结构体和全局变量,全局变量的操作接口,分析了下LFS文件操作接口。

如果大家想更加深入的学习 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/28161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gbase8s数据库阻塞检查点和非阻塞检查点的执行机制

1. 检查点的描述 为了便于数据库系统的复原和逻辑恢复&#xff0c;数据库服务器生成的一致性标志点&#xff0c;称为检查点&#xff0c;其是建立在数据库系统的已知和一致状态时日志中的某个时间点检查点的目的在于定期将逻辑日志中的重新启动点向前移动 如果存在检查点&#…

Windows 服务器Nginx 下载、部署、配置流程(图文教程)

不定期更新 目录 一、下载Nginx安装包 二、上传安装包 三、启动Nginx 四、Nginx常用命令 五、Nginx&#xff08;最小&#xff09;配置详解 六、Nginx&#xff08;基础&#xff09;配置详解 七、反向代理 八、负载均衡 九、动静分离 十、报错 一、下载Nginx安装包 四…

【源码】综合股票币币合约交易所源码/etf交易所源码/美股港股台股交易所源码

支持多国语言 全开源可二开的一个版本&#xff01;支持虚拟货币 ETF 外汇 美股 A股 港股 台股。 前端是VUE开发&#xff08;带vue工程源码&#xff09;后端JAVA开发&#xff01;搭建也相对简单。 总的来说功能非常强大&#xff0c;适合线上运营的一个版本&#xff0c;有兴趣的可…

【因果推断python】38_预测模型1

目录 工业界中的机器学习 之前的部分涵盖了因果推理的核心。那里的技术是众所周知和成熟的。他们经受住了时间的考验。第一部分建立了我们可以依赖的坚实基础。用更专业的术语来说&#xff0c;第一部分侧重于定义什么是因果推理&#xff0c;哪些偏差会阻止相关性成为因果关系&…

Techo TVP技术 沙龙

Techo TVP技术 沙龙 今天参加了 在上海 徐汇 腾讯云大厦 举办的 Techo TVP 技术沙龙&#xff08;主要介绍 AI agent 让我感受很深&#xff09; &#xff0c;那什么是 AI Agent呢&#xff1f; 是一个智能体&#xff0c;由大语言模型驱动&#xff0c;具有自主理解、感知、规划、…

MISSING COURSE-shell

shell 01 what is the shell q: linux如何操作计算机硬件cpu 内存 磁盘 显示器等 a:使用linux的内核操作 1.shell -is命令 shell通过编写shell命令 发送给linux内核 去执行 操作就是计算机硬件 so shell 是用户操作计算机 类似于windows里的dos命令 shell是一门程序设计语言…

《分析模式》漫谈03- Unified Method并不是RUP

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 在《分析模式》第2章 &#xff0c;Fowler提到了“Rational Softwares Unified Method”&#xff0c; 而且给出了引用的参考文献&#xff0c;是Rational公司的一份文档&#xff1a; 200…

数字电路中二进制的数据表达

文章目录 1. 二进制数据表达 1.1 二进制简介 1.2 用二进制表达文字 1.2.1 最开始的表达方式 1.2.2 通讯系统的编码和解码 1.2.3 集成电路 1.2.4 ASCII编码 1.2.5 GBK编码 1.2.6 Unicode编码 2. 用二进制表达图像 2.1 图片像素化 2.2 像素数字化 2.3 二值图像 2.4…

Git冲突解决指南:如何优雅地解决代码合并冲突

在团队协作开发中&#xff0c;使用版本控制系统Git是非常常见的。然而&#xff0c;在多人同时对同一文件进行修改时&#xff0c;就可能出现代码合并冲突。这时就需要我们学会如何优雅地解决这些冲突&#xff0c;保证代码的完整性和质量。本文将为您介绍Git冲突解决的基本原则和…

string类的使用手册

1.构造函数 补充&#xff1a;npos&#xff1a;size_t类型数据的最大值 default (1) string(); 构造空的string类对象 copy (2) string (const string& str); 拷贝构造函数&#xff08;深拷贝&#xff09; substring (3) string (const string& str, size_t pos, size_…

自动化测试火狐下载文件

本篇文章介绍selenium中火狐浏览器如何下载文件。比如我想把这个MP4的视频文件下载下来。 点击之后查看下载的类型是video/mp4 指定使用火狐浏览器 profile webdriver.FirefoxOptions() # 设置firefox默认的下载路径&#xff0c;0表示桌面&#xff0c;1表示我的下载&#xf…

Qt自定义日志输出

Qt自定义日志输出 简略版&#xff1a; #include <QApplication> #include <QDebug> #include <QDateTime> #include <QFileInfo> // 将日志类型转换为字符串 QString typeToString(QtMsgType type) {switch (type) {case QtDebugMsg: return "D…

Mysql的联合索引

一、前言 上一篇中已经讲过了索引相关的知识&#xff0c;为什么还要在讲一下联合索引&#xff08;二级索引&#xff09;&#xff0c;是因为这个知识点特别重要&#xff0c;不论是在面试中&#xff0c;还是在实际的使用过程中&#xff0c;理解和掌握联合索引&#xff0c;是我们…

回归预测 | Matlab实现GWO-ESN基于灰狼算法优化回声状态网络的多输入单输出回归预测

回归预测 | Matlab实现GWO-ESN基于灰狼算法优化回声状态网络的多输入单输出回归预测 目录 回归预测 | Matlab实现GWO-ESN基于灰狼算法优化回声状态网络的多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现GWO-ESN基于灰狼算法优化回声状态…

DevOps学习回顾01-技能发展路线-岗位能力-体系认知(射箭和拉弓的区别)

事为先&#xff0c;人为重–事在人为 参考来源&#xff1a; 极客时间专栏&#xff1a;DevOps实战笔记&#xff0c;作者&#xff1a;石雪峰 课程链接&#xff1a;https://time.geekbang.org/column/intro/235 时代的典型特征 VUCA VUCA 是指易变性&#xff08;Volatility&…

【MySQL】聊聊数据库是如何保证数据不丢的

对于一个存储系统来说&#xff0c;其中比较关键的核心组件包含&#xff0c;网络、存储模型、持久化、数据结构等。而数据如何保证不丢失&#xff0c;对于不同的存储系统来说&#xff0c;比如Redis采用AOF和RDB的方式进行混合使用&#xff0c;而MySQL采用日志进行保证。也就是re…

MyBatis使用Demo

文章目录 01、Mybatis 意义02、Mybatis 快速入门04、Mapper 代理开发05、Mybatis 配置文件07、查询所有&结果映射08、查询-查看详情09、查询-条件查询10、查询-动态条件查询多条件动态查询单条件动态查询 11、添加&修改功能添加功能修改功能 12、删除功能删除一个批量删…

ubuntu 18.04 安装vnc

如何在Ubuntu 18.04安装VNC | myfreax sudo apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils sudo apt install tigervnc-standalone-server tigervnc-common vncserver sudo apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils sudo apt ins…

滴滴出行 大数据研发实习生【继任】

大数据研发实习生JD 职位描述 1、负责滴滴核心业务的数据建设&#xff0c;设计并打造适应滴滴一站式出行平台业务特点的数仓体系。 2、负责抽象核心业务流程&#xff0c;沉淀业务通用分析框架&#xff0c;开发数仓中间层和数据应用产品。 3、负责不断完善数据治理体系&#xff…

Excel报表

(Apache POI) 入门案例 P164 使用POI需要导入下面2个坐标&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId> </dependency> <dependency><groupId>org.apache.poi</groupId>&…