文件系统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.hqwc.cn/news/545254.html

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

相关文章

单片机第四季-第一课:RTOS

1&#xff0c;RTOS来龙去脉 操作系统是什么&#xff1f; 以人类社会类比&#xff0c;小公司三四个人都是干活的&#xff0c;大公司有几万人其中有几千人从事管理工作&#xff0c;他们的工作是让其他人的干活效率更高。 51单片机为什么没有操作系统&#xff0c;因为51的性能太…

鲸鱼优化算法双馈风电机组一次调频三机九节点虚拟惯量下垂控制DFIG matlab/simulink

以频率偏差变化最小为优化目标&#xff0c;采用鲸鱼算法优化风电机组一次调频控制系数。 采用matlab.m文件与simulink.slx文件联合。 系统频率优化结果 鲸鱼算法 时域模型

Gatling压力测试Springboot项目

Gatling压力测试Springboot项目 一、指定Java Spring 项目作为测试项二、下载Gatling三、配置测试代码四、打开bin目录下的gatling.bat文件进行测试 一、指定Java Spring 项目作为测试项 这里给出一个简单的示例&#xff1a;代码链接 下载maven依赖以后在8080端口运行这个项目…

章鱼网络 Community Call #19|​开启与 Eigenlayer 的合作

香港时间2024年3月8日12点&#xff0c;章鱼网络举行第19期 Community Call。 在过去的一个月&#xff0c;章鱼网络在成功完成 $NEAR Restaking 功能的安全审计之后&#xff0c;一直在稳步吸引关注。事实上&#xff0c;在整个行业中&#xff0c;我们是极少数已经推出 Restaking …

iOS常见崩溃简介

1. 崩溃 多指在移动设备&#xff08;如iOS、Android设备&#xff09;中或不可移动设备&#xff08;如:Windows、Linux等设备&#xff09;&#xff0c; 在打开或使用应用程序时出现的突然退出中断的情况&#xff08;类似于Windows的应用程序崩溃&#xff09;。 多表现为&#…

基于springboot+vue实现艺术水平考级报名系统【项目源码+论文说明】计算机毕业设计

基于springbootvue实现艺术水平考级报名系统演示 摘要 本次毕业设计基于SpringBoot框架开发了一款艺术水平考级报名管理系统。该系统为考生提供了线上报名、准考证管理等核心功能&#xff0c;并为系统管理员提供了在线发布考试信息、对报名考生进行审核等管理功能。通过该系统…

从政府工作报告中的IT热词统计探计算机行业发展(二)人工智能+:3次

政府工作报告作为政府工作的全面总结和未来规划&#xff0c;不仅反映了国家整体的发展态势&#xff0c;也为各行各业提供了发展的指引和参考。随着信息技术的快速发展&#xff0c;计算机行业已经成为推动经济社会发展的重要引擎之一。因此&#xff0c;从政府工作报告中探寻计算…

基于VJ算法(Viola-Jones algorithm)的人面定位算法,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

Python之Web开发中级教程----搭建Web框架二

Python之Web开发中级教程----搭建Web框架二 搭建虚拟环境 虚拟环境的作用 虚拟环境可以搭建独立的python运行环境, 使得单个项目的运行环境与其它项目互不影响. 搭建虚拟环境 &#xff08;1&#xff09;安装 sudo pip install virtualenv sudo pip install virtualenvwra…

JAVA13多行文本java14模式变量

文章目录 多行文本模式变量 多行文本 在JAVA13中&#xff0c;终于是支持多行文本字面量了。而且最关键的是为了源代码更加美观&#xff0c;还自动去掉了每行文本前面的空格。如下面的例子&#xff1a; public class MultilineStringDemo {public static void main(String[] ar…

静态库与动态库的制作和使用

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 前言 库&#xff1f; 为什么要使用库 静态库 静态库的制作和使用 动态库 动态库的制作和使用 四种方法&#xff1a; 直接将库拷贝(安装)到系统路径中 配置环境变量 软链接 添加配置文件 动态库和静态库同时…

【Hadoop大数据技术】——MapReduce经典案例实战(倒排索引、数据去重、TopN)

&#x1f4d6; 前言&#xff1a;MapReduce是一种分布式并行编程模型&#xff0c;是Hadoop核心子项目之一。实验前需确保搭建好Hadoop 3.3.5环境、安装好Eclipse IDE &#x1f50e; 【Hadoop大数据技术】——Hadoop概述与搭建环境&#xff08;学习笔记&#xff09; 目录 &#…