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

news2024/11/16 5:25:44

文件系统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.coloradmin.cn/o/1526851.html

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

相关文章

Auto-DataProcessing:一组让制作数据集变轻松的脚本

前言 最近跟同学参加了个比赛&#xff0c;我负责Object-Detection的技术实现&#xff0c;需要从网上扒大量的数据(主办方每种识别物就给了一张demo&#x1f923;)&#xff0c;发现数据准备是一个真的是一个非常重要但又耗时耗力的过程。对我来说&#xff0c;给我一类待识别的标…

蓝桥之手撕排序算法——冒泡、选择、插入、快排、归并(Python版)

目录 1. 排序引言 2. 冒泡排序 2.1 算法思想 2.2 代码实现 2.3 时空复杂度分析 3. 选择排序 3.1 算法思想 3.2 代码实现 3.3 时空复杂度分析 4. 插入排序 4.1 算法思想 4.3 代码实现 4.4 时空复杂度分析 5. 快速排序 5.1 算法思想 5.2 代码实现 5.3 时空复杂度分…

upload-labs 0.1 靶机详解

下载地址https://github.com/c0ny1/upload-labs/releases Pass-01 他让我们上传一张图片&#xff0c;我们先尝试上传一个php文件 发现他只允许上传图片格式的文件&#xff0c;我们来看看源码 我们可以看到它使用js来限制我们可以上传的内容 但是我们的浏览器是可以关闭js功能的…

【开发】SpringBoot 整合 Redis

目录 前言 1. Redis 的下载及安装 1.1 Redis 的下载 1.2 安装 Redis 1.3 启动 Redis 2. 创建 SpringBoot 项目整合 Redis 2.1 环境要求 2.2 SpringBoot项目构建 2.2.1 方式一 2.2.2 方式二 2.3 在 pom.xml 文件中导入依赖坐标 2.4 在 application.properties 中加…

解释器模式(Interpreter Pattern)

解释器模式 说明 解释器模式&#xff08;Interpreter Pattern&#xff09;属于行为型模式&#xff0c;是指给定一门语言&#xff0c;定义它的语法&#xff08;文法&#xff09;的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。是一…

CVX安装新版本Mosek求解器

在使用连续凸近似&#xff08;SCA&#xff09;求解优化问题时遇到了报错 Problem status : ILL_POSED Solution status : PRIMAL_ILLPOSED_CER并且最后给出的结果为NaN。 在CVX论坛中找到一条回答 具体链接如下&#xff1a; The status is failed 因为我使用的是CVX自带的…

批量查询快递信息,固乔助手助您高效处理

在物流、供应链等行业&#xff0c;每天都需要处理大量的快递信息。无论是物流公司还是供应链企业&#xff0c;都需要实时掌握每一个包裹的状态和位置。然而&#xff0c;当面对成千上万的快递单号时&#xff0c;如何高效地查询这些信息成为了一个亟待解决的问题。 传统的查询方式…

IDEA直接打包Docker镜像

以下为使用IDEA打包Docker镜像并推送到远程仓库&#xff08;使用Windows打包Docker镜像并推送到远程仓库&#xff09;教程 1 安装Docker Desktop 下载地址&#xff1a;https://www.docker.com/products/docker-desktop/ 安装成功后&#xff0c;可在cmd查看版本号 2 启动Do…

Machine Learning ---- Feature Scaling

目录 一、What is feature scaling:&#xff1a; 二、Why do we need to perform feature scaling? 三、How to perform feature scaling: 1、Normalization: 2、Mean normalization: 3、Standardization (data needs to follow a normal distribution): 一、What is featur…

膨胀 卷积

1.作用 Dilated convolution、Atrous convolution 增大感受野保持原输入大小 2.膨胀因子 描述的是相邻元素之间的距离 r 2 3.gridding effect 不合理的多个膨胀卷积之前&#xff0c;设计的膨胀因子不合理导致&#xff0c;在增大感受野的同时丢失了细节信息。 丢失&…

【SpringCloud】使用Seata实现分布式事务

目录 一、Seata 框架的需求背景二、Seata 事务模式与架构2.1 Seata 组成2.2 Seata 事务模式 三、Seata 实战演示3.1 部署 Seata Server3.1.1 下载 Seata Server3.1.2 更改 Seata Server 配置3.1.3 创建 Seata Server 所需的数据库、数据库表3.1.4 启动 Seata Server 3.2 Seata …

判断闰年(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int year 2000;//执行循环判断&#xff1b;while (year < 2010){//执行流程&#xff1b;//判断能否整除4&#xff1…

十二、CyclicBarrier

CyclicBarrier 栅栏 什么时候满了开始发车 CyclicBarrier barrier new CyclicBarrier(20, () -> System.out.println("满人"));满20人开始发车每一个线程到达 barrier.await();都等着当 barrier.await();到达20人就开始往下执行 &#xff0c;发车 public…

struts2 CVE-2021-31805-struts2 s2-061 ONGL远程代码执行复现

复现&#xff1a; 切换到vulhub开启并且查看靶场的端口 访问页面 我们可以输入下面的命令来测试一下&#xff0c;执行6*6&#xff0c;查看源代码发现可以成功运行 接下来我们可以注入下面的payload来进行代码执行&#xff0c;执行id来查看当前用户 POST / HTTP/1.1 Host: x.x.…

探索Spring中的属性注入:@Value注解解析与应用

探索Spring中的属性注入&#xff1a;Value注解解析与应用 探索Spring中的属性注入&#xff1a;Value注解解析与应用摘要引言正文作用代码准备示例注入字符串注入属性注入Bean及其属性 其他属性注入优先级问题对Value属性注入的扩展Spring Boot对Value类型转换的扩展 代码案例演…

【GameFramework框架内置模块】8、文件系统(File System)

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录&#xff1a; https://blog.csdn.net/q7…

代码随想录算法训练营第二十七天(第二十六天休息)|40.组合总和II

40.组合总和II 题目 给定一个数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 说明&#xff1a; 所有数字&#xff08;包括目标数&#xff09;都是正整数。解集…

Android 开发环境搭建(Android Studio 安装图文详细教程)

Android Studio 下载 https://developer.android.google.cn/studio?hlzh-cn Android Studio 安装 检查电脑是否启用虚拟化 如果没有开启虚拟化&#xff0c;则需要进入电脑的 BIOS 中开启 直接 next选择安装的组件&#xff0c;Android Studio 和 Android 虚拟设备&#xff…

使用蜂鸟地图完成楼层自定义、房间着色、热力图、添加图片覆盖物、添加dom覆盖物、定位到固定区域的中心点

项目里有用到蜂鸟地图的地方&#xff0c;虽然有跟她们对接&#xff0c;但看他们文档也挺费劲的&#xff0c;要自己慢慢研究好久&#xff0c;有些实在研究不出来让他们帮忙看代码发现一些问题&#xff0c;所以把我发现的需要注意的一些点发上来&#xff0c;希望可以帮助到部分有…

深入探讨ChatGPT:技术突破与应用前景

目录 一、ChatGPT究竟是什么&#xff1f; 二、ChatGPT的发展脉络 三、ChatGPT的突出优势 强大的语言生成能力 多场景适应性 多语言处理能力 广泛的应用范围 数据敏感性的重视 四、结语&#xff1a;ChatGPT的未来与挑战 Tips&#xff1a;国内的ChatGPT ⭐ 点击进入Chat…