文件系统I/O FATFS RW 源码分析

文件系统I/O FATFS RW 源码分析

0 参考

FatFs 是用于小型嵌入式系统的通用 FAT/exFAT 文件系统模块。FatFs 整个项目都按照 ANSI C (C89) 编写。与存储器 I/O 解耦良好,便于移植到 8051、PIC、AVR、ARM、Z80、RX 等小型微控制器中。

下面是关于 FAT 文件系统格式和 FATFS 项目的文档链接。

  1. FatFs - Generic FAT Filesystem Module
  2. The basics of FAT filesystem
  3. Microsoft Extensible Firmware Initiative FAT32 File System Specification

1 如何写入

FATFS 提供了一系列使用例程,通过 FATFS 接口把数据写入文件系统的流程如下:

  1. 挂载文件系统
f_mount(&FatFs, "", 0);		/* Give a work area to the default drive */
  1. 根据文件路径打开文件
fr = f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS);	/* Create a file */
  1. 把数据写入文件
f_write(&Fil, "It works!\r\n", 11, &bw);	/* Write data to the file */
  1. 关闭文件
fr = f_close(&Fil);							/* Close the file */

如上,FATFS 的使用和我们在桌面操作系统上读写文件大差不差,使用这个包可以让我们在在 MCU 上存取数据时获得操作系统级的体验。下面是一个完整的 DEMO.

example

/*----------------------------------------------------------------------*/
/* Foolproof FatFs sample project for AVR              (C)ChaN, 2014    */
/*----------------------------------------------------------------------*/#include <avr/io.h>	/* Device specific declarations */
#include "ff.h"		/* Declarations of FatFs API */FATFS FatFs;		/* FatFs work area needed for each volume */
FIL Fil;			/* File object needed for each open file */int main (void)
{UINT bw;FRESULT fr;f_mount(&FatFs, "", 0);		/* Give a work area to the default drive */fr = f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS);	/* Create a file */if (fr == FR_OK) {f_write(&Fil, "It works!\r\n", 11, &bw);	/* Write data to the file */fr = f_close(&Fil);							/* Close the file */if (fr == FR_OK && bw == 11) {		/* Lights green LED if data written well */DDRB |= 0x10; PORTB |= 0x10;	/* Set PB4 high */}}for (;;) ;
}

2 f_write()里做了什么

2.1 逐行分析源码

为了搞清楚 FATFS 的写操作逻辑,我们需要逐行分析 f_write() 的实现。

查看源码,立即就能发现 f_write() 调用了一个名为 disk_write 的函数,这很可能就包含着操作 磁盘/SD 卡等存储介质的底层实现。

if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);

disk_write() 的原型如下:

DRESULT disk_write (BYTE drv,			/* Physical drive nmuber (0) */const BYTE *buff,	/* Pointer to the data to be written */LBA_t sector,		/* Start sector number (LBA) */UINT count			/* Sector count (1..128) */
)

参数 buffcount 很好理解,就是数据缓存和数据大小,无需多言。

参数 sector 则由“簇数” fp->clust计算得到:

sect = clst2sect(fs, fp->clust);	/* Get current sector */

fp->clustfp->obj 中读出, 这个变量在 f_open() 中被初始化。

clst = fp->obj.sclust;	/* Follow from the origin */
...
fp->clust = clst;			/* Update current cluster */

drv 的值即 disk_write() 的第一个参数 fs->pdrv 的值, fs 在 f_write() 开头的有效性检查 validate() 那里被初始化,初始化时刻如下所示:

static FRESULT validate (	/* Returns FR_OK or FR_INVALID_OBJECT */FFOBJID* obj,			/* Pointer to the FFOBJID, the 1st member in the FIL/DIR structure, to check validity */FATFS** rfs				/* Pointer to pointer to the owner filesystem object to return */
){
...*rfs = (res == FR_OK) ? obj->fs : 0;	/* Return corresponding filesystem object if it is valid */return res;
}

2.2 总结一下 f_write()

做了什么:

  • 解析在 f_open() 中初始化的 fp
  • 获取给定文件路径对应的簇号(cluster number)并转换成扇区号(sector number)
  • 获取文件系统的物理驱动号(即fp 对应的区域在哪个物理设备/磁盘上)
  • 以驱动号、扇区号、数据和数据大小为参数调用 disk_write()

3 我们实际上关心的是什么

依据上面的分析,我们已经知道我们可以通过修改 disk_write() 的实现来适配不同的存储设备。

但我们真正关心的是,如何在磁盘上找到某个文件,所以我们还需要分析 f_open() 的实现。

3.2 f_open() 里做了什么

下面是 f_open 运行时的调用树,看起来整个 open 的过程像是在树状结构中做检索。我想那么,也许有必要看看 FAT 文件系统的原始定义,也即文件系统的镜像格式。

f_open()

follow_path()

create_name() // iterator of dir name in file path
dir_find()

dir_sdi()

get_fat() // get fat32 entry, ret cluster number
clst2sect() // transfrom cluster number to section number

回到文件系统的镜像格式

FAT(File Allocation Table),最早在DOS v1.0 中被引入,是一种极简的文件系统,占用空间,是目前最常见的文件系统之一。FAT 文件系统有多种历史版本,比如 FAT12/FAT16/FAT32/exFAT/VFAT,这里只介绍 FAT32,

使用 FAT 管理的存储介质分为三个基本区域:

  • 启动记录 (The boot record)
  • 文件分配表 (FAT,The File Allocation Table)
  • 目录和数据区(The directory and data area)

“The boot record”(引导记录)是指存储在磁盘的第一个扇区的特殊区域。它也被称为引导扇区(boot sector)或主引导记录(master boot record,MBR)。

FAT32 的主引导扇区可分为两部分,前 36 字节与其他版本的 FAT 一致,36 字节以后的区域划分如下图所示。

在这里插入图片描述

origin_url=.%2Fbehind36.png&pos_id=img-nzYYNo5c-1710653498658)

偏移 44 字节处为根目录所在的扇区(通常为2),打开文件系统镜像,转到对应扇区,可见目录中的文件列表如下。

在这里插入图片描述

额外提一句,FAT 文件系统中的时间记录以 1980 年 1 月 1 日为基准,如上图偏移0x10位置的两个字节为0X3C21,高 7 位表示年,数值为30,对应的年份为 1980+30=2010 年。

在这里插入图片描述

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

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

相关文章

20.回文链表

给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;head …

linux 安装常用软件

文件传输工具 sudo yum install –y lrzsz vim编辑器 sudo yum install -y vimDNS 查询 sudo yum install bind-utils用法可以参考文章 《掌握 DNS 查询技巧&#xff0c;dig 命令基本用法》 net-tools包 yum install net-tools -y简单用法&#xff1a; # 查看端口占用情况…

【学习学习】学习金字塔

学习金字塔&#xff08;Cone of Learning&#xff09;&#xff0c;全称学习吸收率金字塔&#xff0c;是一种现代学习方式的理论。网上流传它是美国缅因州的国家训练实验室&#xff08;National Training Laboratories&#xff09;研究成果&#xff0c;用数字形式形象显示了采用…

【重温设计模式】观察者模式及其Java示例

观察者模式的概念和原理 在编程世界中&#xff0c;设计模式作为一种解决问题的策略&#xff0c;它的存在就如同人类语言中的成语&#xff0c;是一种经过时间考验的有效解决方案。 观察者模式就是其中一种重要的设计模式&#xff0c;它在很多场景中都有着广泛的应用。那么&…

外包干了5天,技术退步明显。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…

Java项目:63 ssm网上花店设计+vue

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统具备友好性且功能完善。管理员登录进入后台之后&#xff0c;主要完成花材选择管理&#xff0c;用户管理&#xff0c;鲜花管理&#xff0c;鲜花出入…

【数据结构与算法】(16):桶除了能装饭还能排序?

&#x1f921;博客主页&#xff1a;Code_文晓 &#x1f970;本文专栏&#xff1a;数据结构与算法 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&…

源神,启动!马斯克开源史上最大模型Grok,参数高达3140亿,可商用!

马斯克真不愧是源神&#xff0c;自开源X的推荐算法以及特斯拉智能驾驶算法后&#xff0c;又说到做到&#xff0c;开源旗下大模型Grok&#xff01; 代码和模型权重已上线GitHub。官方信息显示&#xff0c;此次开源的Grok-1是一个3140亿参数的混合专家模型&#xff0c;远超OpenAI…

HTML选择文件的实时预览

HTML选择文件的实时预览 目录 HTML选择文件的实时预览HTML代码JS代码预览 HTML代码 <input type"file" id"adv_img_input" style"width: 1000px ;height:30px"> <img src"#"id"adv_img">JS代码 <script>…

配置OGG 如何批量修改源端及目标端序列值_满足客户变态需求学会这招你就赚了

欢迎您关注我的公众号【尚雷的驿站】 **************************************************************************** 公众号&#xff1a;尚雷的驿站 CSDN &#xff1a;https://blog.csdn.net/shlei5580 墨天轮&#xff1a;https://www.modb.pro/u/2436 PGFans&#xff1a;ht…

WanAndroid(鸿蒙版)开发的第三篇

前言 DevEco Studio版本&#xff1a;4.0.0.600 WanAndroid的API链接&#xff1a;玩Android 开放API-玩Android - wanandroid.com 其他篇文章参考&#xff1a; 1、WanAndroid(鸿蒙版)开发的第一篇 2、WanAndroid(鸿蒙版)开发的第二篇 3、WanAndroid(鸿蒙版)开发的第三篇 …

2024年3月GESP认证Scratch图形化编程四级真题及答案

GESP 图形化四级试卷 &#xff08;满分&#xff1a;100 分 考试时间&#xff1a;120 分钟&#xff09; 学校&#xff1a; 姓名&#xff1a; ​ 一、单选题&#xff08;共 10 题&#xff0c;每题 2 分&#xff0c;共 30 分&#xff09; 题号 1 2 3 4 5 6 7 8 9 10 11 1…

【开源】SpringBoot框架开发学生综合素质评价系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生功能2.2 教师功能2.3 教务处功能 三、系统展示四、核心代码4.1 查询我的学科竞赛4.2 保存单个问卷4.3 根据类型查询学生问卷4.4 填写语数外评价4.5 填写品德自评问卷分 五、免责说明 一、摘要 1.1 项目介绍 基于J…

数字化转型导师坚鹏:人工智能在金融机构数字化转型中的应用

人工智能在金融机构数字化转型中的应用 课程背景&#xff1a; 金融机构数字化转型离不开人工智能&#xff0c;在金融机构数字化转型中&#xff0c;人工智能起到至关重要的作用&#xff0c;很多机构存在以下问题&#xff1a; 不清楚人工智能产业对我们有什么影响&#xff1f;…

考研数学|概率应该怎么学?

考研概率论老师很多&#xff0c;但是我最推荐两个老师&#xff0c;李良和方浩 我认为李良概率论基础讲解相比于其他老师最大的优点就是&#xff0c;每一步都会耐心解释其中的逻辑。很少会像方浩老师那样过于跳跃或者频繁串联&#xff0c;这点对于零基础思维转换慢的人来说&…

Transformer self-attention源码及原理理解

自注意力计算公式&#xff1a; 在公式(1)中Q(query)是输入一个序列中的一个token&#xff0c;K(key)代表序列中所有token的特征。 可以得到当前token与序列中其他token的相关性。在论文原文中512&#xff0c;表示每个token用512维特征表示&#xff08;序列符号的embedding长度…

C语言中大小写字母如何转化

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

Linux TCP参数——tcp_adv_win_scale

文章目录 tcp_adv_win_scaleip-sysctl.txt解释buffering overhead内核缓存和应用缓存示例计算深入理解从2到1(tcp_adv_win_scale的值)总结 tcp_adv_win_scale adv-advise&#xff1b;win-window; 用于指示TCP中接收缓存比例的值。 static inline int tcp_win_from_space(int …

SpringSecurity(SpringBoot2.X版本实现)

资料来源于 SpringSecurity框架教程-Spring SecurityJWT实现项目级前端分离认证授权 侵权删 目录 介绍 快速开始 认证 认证流程 登录校验流程 SpringSecurity完整流程 认证流程详解 代码实现 准备工作 mysql mybatis-plus redis 统一返回类 核心代码 密码加密存…

Mesh网格obj文件构成解析

众所周知&#xff0c;Mesh网格是三维重建的常用手法&#xff0c;通过顶点-三角面的形式来完成对三维物体的表达。其中&#xff0c;最常见的Mesh网格文件格式就是obj格式。看起来复杂的三维形状其实在数值表示上是很简单的&#xff0c;大家跟我一起来做个小实验就好&#xff1a;…