文件系统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 年。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Exception系列】SocketTimeoutException

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

ADO .Net操作SQL Server数据库

//ADO.NET是.NET Framework提供的数据访问服务的类库&#xff0c;应用程序可以使用ADO.NET连接到这些数据源&#xff0c;并检索、处理和更新数据 //常用的数据源包括四种&#xff1a;&#xff08;1&#xff09;Microsoft SQL Server数据源&#xff1a;使用System.Data.SqlClien…

STM32---SG90舵机控制(HAL库,含源码)

写在前面&#xff1a;在嵌入式的项目中&#xff0c;舵机是一个十分常见的元器件模块&#xff0c;其主要的功能是实现机械转动&#xff0c;实质上舵机是一个伺服的驱动器&#xff0c;适用于那些需要角度不断变化并可以保持的控制系统。例如在机器人的电控制器系统中&#xff0c;…

Java8中Stream流API最佳实践Lambda表达式使用示例

文章目录 一、创建流二、中间操作和收集操作筛选 filter去重distinct截取跳过映射合并多个流是否匹配任一元素&#xff1a;anyMatch是否匹配所有元素&#xff1a;allMatch是否未匹配所有元素&#xff1a;noneMatch获取任一元素findAny获取第一个元素findFirst归约数值流的使用中…

在线BLOG网|基于springboot框架+ Mysql+Java+JSP技术的在线BLOG网设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunwen参考 摘要 研究…

C语言学习过程总结(18)——指针(6)

一、数组指针变量 在上一节中我们提到了&#xff0c;指针数组的存放指针的数组&#xff0c;那数组指针变量是什么呢&#xff1f; 显而易见&#xff0c;数组指针变量是指针 同样类比整型指针变量和字符指针变量里面分别存放的是整型变量地址和字符变量地址&#xff0c;我们可以…

每周AI新闻(2024年第11周)Meta公布Llama 3集群细节 | Sora将于年内推出 | 全球首个AI软件工程师发布

这里是陌小北&#xff0c;一个正在研究硅基生命的碳基生命。正在努力成为写代码的里面背诗最多的&#xff0c;背诗的里面最会写段子的&#xff0c;写段子的里面代码写得最好的…厨子。 每周日解读每周AI大事件。 欢迎关注同名公众号【陌北有棵树】&#xff0c;关注AI最新技术…

第二十四天-数据可视化Matplotlib

目录 1.介绍 2.使用 1. 安装&#xff1a; 2.创建简单图表 3.图表类型 1.一共分为7类 2.变化 1.折线图 3.分布 ​编辑 1.直方图 2.箱型图 4.关联 1. 散点图&#xff1a; 2.热力图&#xff1a; 5.组成 1.饼图 2.条形图 6.分组 1.簇型散点图 2.分组条形图 3.分…

【ollama】linux、window系统更改模型存放位置,全网首发2024!

首先是window系统 so easy 直接进入系统环境变量添加就行 其次是linux系统 全靠自己试出来的,去Ollama官网找半天文档不知道在哪,而且linux也没有说:【 https://github.com/ollama/ollama/blob/main/docs/README.md https://github.com/ollama/ollama/blob/main/docs/li…

Ubuntu 如何安装 Beyond Compare?

Ubuntu20.04安装Beyond Compare 4.3.7 一、官网下载方式一&#xff1a;方法二&#xff1a;使用 .deb 包安装 二、安装相关依赖和bcompare三、破解常见错误解决方法 ) 文件比较工具Beyond Compare是一套由Scooter Software推出的文件比较工具。主要用途是对比两个文件夹或者文件…

HCIA——30奈奎斯特定理、香农定理

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:TextTimer)

通过文本显示计时信息并控制其计时器状态的组件。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 TextTimer(options?: TextTimerOptions) 参数&#xff1a; 参数名参数类型…

Kotlin进阶之协程从入门到放弃

公众号「稀有猿诉」 原文链接 Kotlin进阶之协程从入门到放弃 协程Coroutine是最新式的并发编程范式&#xff0c;它是纯编程语言层面的东西&#xff0c;不受制于操作系统&#xff0c;轻量级&#xff0c;易于控制&#xff0c;结构严谨&#xff0c;不易出错&#xff0c;易于…

深入浅出理解 AI 生图模型

目录 引言 一、Stable Diffusion原理 首先 随后 最后 二、DDPM模型 1 资料 2 原理 扩散过程 反向过程 3 公式结论 三、优缺点 优点&#xff1a; 缺点&#xff1a; 四、改进与完事 LDM代表作 原理概括 Latent Space&#xff08;潜空间&#xff09; 五、总结 引…

提高安全投资回报:威胁建模和OPEN FAIR™风险分析

对大多数人和企业来说&#xff0c;安全意味着一种成本。但重要的是如何获得适合的量&#xff0c;而不是越多越好。然而&#xff0c;你如何决定什么时候可以有足够的安全性&#xff0c;以及你如何获得它&#xff1f;则完全是另一回事。 该篇文章是由The Open Group安全论坛主办&…

【PyTorch】进阶学习:一文详细介绍 load_state_dict() 的应用场景、实战代码示例

【PyTorch】进阶学习&#xff1a;一文详细介绍 load_state_dict() 的应用场景、实战代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入…

vb.net+zxing.net随机彩色二维码、条形码

需要zxing库支持ZXing.NET Generate QR Code & Barcode in C# Alternatives | IronBarcode 效果图&#xff1a; 思路&#xff1a;先生成1个单位的二维码&#xff0c;然后再通过像素填充颜色&#xff0c;颜色数组要通过洗牌算法 洗牌算法 Dim shuffledCards As New List(…

C#控制台贪吃蛇

Console.Write("");// 第一次生成食物位置 // 随机生成一个食物的位置 // 食物生成完成后判断食物生成的位置与现在的蛇的身体或者障碍物有冲突 // 食物的位置与蛇的身体或者障碍物冲突了&#xff0c;那么一直重新生成食物&#xff0c;直到生成不冲突…

GenAI开源公司汇总

主要分类如下&#xff1a; 1. 基础模型&#xff1a;这些是机器学习和AI的核心模型提供商&#xff0c;它们提供基础的算法和技术支持。 2. 模型部署与推断&#xff1a;提供云服务和计算资源&#xff0c;帮助用户部署和运行AI模型。 3. 开发者工具&#xff1a;支持AI/ML的开发…

【网络原理】TCP 协议中比较重要的一些特性(三)

目录 1、拥塞控制 2、延时应答 3、捎带应答 4、面向字节流 5、异常情况处理 5.1、其中一方出现了进程崩溃 5.2、其中一方出现关机&#xff08;正常流程的关机&#xff09; 5.3、其中一方出现断电&#xff08;直接拔电源&#xff0c;也是关机&#xff0c;更突然的关机&am…