深入了解FAT文件系统

FAT(File Allocation Table,文件分配表)文件系统是由微软开发的一种简单高效的文件系统格式。它广泛应用于各种存储设备,如U盘、SD卡等。本文将详细介绍FAT文件系统的关键术语、结构和功能实现,帮助读者全面了解这一经典文件系统。

目录

  1. 关键术语
  2. FAT文件系统结构
    • Volume Structure
    • Boot Sector and BPB
    • FAT文件分配表
    • File System Information (FSInfo) Structure
    • Directory Structure
    • 长文件名实现
  3. 文件系统的工作方式
    • 定位到文件的开始
    • 创建文件
    • 删除文件
    • 增加文件内容
    • 减少文件内容
  4. 结语

关键术语

  • Volume(卷):存储设备上的一个逻辑分区。
  • Sector(扇区):存储设备上的最小存储单位,通常为512字节。
  • Cluster(簇):由一个或多个连续的扇区组成的逻辑存储单位。
  • BPB(BIOS Parameter Block):引导扇区的一部分,包含文件系统的基本参数。
  • FAT(File Allocation Table):用于管理文件簇链的表格。
  • Root Directory(根目录):文件系统的顶级目录,包含文件和子目录的元数据。

FAT文件系统结构

Volume Structure

FAT文件系统卷包含四个基本区域,分别为保留区域、FAT区域、根目录区域和文件及目录数据区域。

  1. Reserved Region (保留区域)

    • 包括卷的第一个扇区,即引导扇区(BPB,BIOS参数块)。
    • 保留区域通常包含引导代码、BIOS参数块和扩展的BPB结构等信息。
  2. FAT Region (FAT区域)

    • 存储文件分配表(FAT),一个用于跟踪文件和目录存储位置的链表结构。
    • FAT区域通常包含一个或多个副本,以提高数据的可靠性。
  3. Root Directory Region (根目录区域)

    • 存在于FAT12和FAT16卷中,但在FAT32卷中不存在。
    • 包含卷的根目录条目,根目录是特殊的目录文件,用于存储根目录中的文件和子目录的条目。
  4. File and Directory Data Region (文件和目录数据区域)

    • 存储实际的文件和目录数据。
    • 文件和目录的数据被分配在一个或多个簇中,并通过FAT区域中的链表进行管理。
Boot Sector and BPB

引导扇区位于卷的第一个扇区,包含BIOS参数块(BPB)。BPB定义了文件系统的基本参数,如每扇区的字节数、每簇的扇区数和保留扇区数。以下是BPB的一些关键字段:

  • BPB_BytsPerSec:每扇区的字节数。
  • BPB_SecPerClus:每簇的扇区数。
  • BPB_RsvdSecCnt:保留扇区数。
  • BPB_NumFATs:FAT表的数量。
  • BPB_RootEntCnt:根目录条目数(FAT12和FAT16)。
  • BPB_TotSec16:卷的总扇区数(如果不超过65535扇区)。
  • BPB_FATSz16:每个FAT表的扇区数(FAT12和FAT16)。
  • BPB_TotSec32:卷的总扇区数(如果超过65535扇区)。
  • BPB_FATSz32:每个FAT表的扇区数(FAT32)。

BPB中的这些字段定义了文件系统的基本几何结构和配置,是解析文件系统的基础。

FAT文件分配表

FAT是文件系统的核心部分,管理着每个簇的分配情况。FAT表中存储了以下内容:

  1. 空闲簇:表示为0x0000,表示该簇是空闲的,可以被分配使用。
  2. 已分配簇:范围在0x0002到最大值之间,表示该簇已被分配并且值为下一个簇的簇号,形成文件簇链。
  3. 保留簇:从最大值加1到0xFFF6之间,这些值是保留的,不应使用。
  4. 坏簇:表示为0xFFF7,表示该簇是坏簇,不能被使用。
  5. 文件结束簇:范围从0xFFF80xFFFE,表示文件的最后一个簇,指示文件结束。
File System Information (FSInfo) Structure

FSInfo结构是FAT32文件系统的一部分,用于存储一些全局的文件系统信息,如剩余空闲簇数和下一个可用簇号。FSInfo结构通常位于卷的第三个扇区。

Directory Structure

目录结构存储文件和子目录的元数据。每个目录项包含以下字段:

  • DIR_Name:文件或目录名。
  • DIR_Attr:文件或目录属性。
  • DIR_FstClusLO:起始簇号的低16位(FAT32)。
  • DIR_FstClusHI:起始簇号的高16位(FAT32)。
  • DIR_FileSize:文件大小。

这些字段用于记录文件或目录的名称、属性、大小和起始位置等关键信息。

长文件名实现

FAT文件系统原本只支持8.3格式的短文件名,即最多8个字符的文件名和3个字符的扩展名。为了支持长文件名,FAT文件系统引入了VFAT(Virtual FAT)扩展。长文件名通过一系列特殊的目录项存储,这些目录项的属性设置为0x0F,表示这是长文件名条目。每个长文件名条目存储部分文件名,并使用校验和来验证完整性。

文件系统的工作方式

定位到文件的开始

要定位到文件的开始,即知道该文件对应的起始簇号(例如簇2),需要通过以下步骤:

  1. 读取根目录或子目录:首先需要读取根目录或者文件所在的子目录,这些目录项中包含了文件的起始簇号。
  2. 获取起始簇号:从目录项中提取出文件的起始簇号。例如,如果目录项中的起始簇号是2,那么文件的第一个数据簇就是簇2。
  3. 计算数据区的起始位置:根据BPB中的信息,计算文件数据区的起始位置。文件数据区是指所有实际存储文件数据的区域。
  4. 根据起始簇号定位文件数据:通过起始簇号,计算出文件在数据区中的具体位置。

以下是具体步骤:

RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
TmpVal1 = DskSize – (BPB_ResvdSecCnt + RootDirSectors);
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
If(FATType == FAT32)
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;
If(FATType == FAT32) {
BPB_FATSz16 = 0;
BPB_FATSz32 = FATSz;
} else {
BPB_FATSz16 = LOWORD(FATSz);
/* there is no BPB_FATSz32 in a FAT16 BPB */
}

通过这些步骤,可以确定文件在FAT文件系统中的具体位置,从而读取或写入文件数据。

创建文件

创建文件的过程涉及以下步骤:

  1. 寻找空闲目录项:在目标目录中找到一个空闲的目录项。
  2. 分配簇:为文件分配一个或多个空闲簇。
  3. 更新FAT表:在FAT表中记录簇链信息。
  4. 填写目录项:在目录项中填写文件名、起始簇号、文件大小等信息。

创建文件示例代码:

// 查找空闲目录项
for (int i = 0; i < RootDirSectors; i++) {if (DirEntry[i].DIR_Name[0] == 0x00 || DirEntry[i].DIR_Name[0] == 0xE5) {// 找到空闲目录项break;}
}// 分配第一个簇
int firstCluster = find_free_cluster();// 更新FAT表
FAT[firstCluster] = 0xFFF;  // 文件结束簇// 填写目录项
DirEntry[i].DIR_Name = "NEWFILE  ";
DirEntry[i].DIR_Attr = ATTR_ARCHIVE;
DirEntry[i].DIR_FstClusLO = firstCluster & 0xFFFF;
DirEntry[i].DIR_FstClusHI = (firstCluster >> 16) & 0xFFFF;
DirEntry[i].DIR_FileSize = 0;
删除文件

删除文件的过程包括以下步骤:

  1. 读取目录项:找到目标文件的目录项。
  2. 释放簇链:在FAT表中释放文件占用的簇链。
  3. 标记目录项为空闲:将目录项的第一个字节标记为0xE5,表示该目录项为空。

删除文件示例代码:

// 查找目标文件
for (int i = 0; i < RootDirSectors; i++) {if (strcmp(DirEntry[i].DIR_Name, "TARGET  ") == 0) {// 找到目标文件break;}
}// 释放簇链
int cluster = (DirEntry[i].DIR_FstClusHI << 16) | DirEntry[i].DIR_FstClusLO;
while (cluster != 0xFFF) {int nextCluster = FAT[cluster];FAT[cluster] = 0x0000;  // 标记为空闲cluster = nextCluster;
}// 标记目录项为空闲
DirEntry[i].DIR_Name[0] = 0xE5;
增加文件内容

增加文件内容时,需要以下步骤:

  1. 找到文件的最后一个簇:读取FAT表,找到文件的最后一个簇。
  2. 分配新簇:如果文件需要扩展,则分配新的空闲簇。
  3. 更新FAT表:在FAT表中链接新的簇。
  4. 写入数据:将新数据写入新的簇。

增加文件内容示例代码:

// 查找文件的最后一个簇
int cluster = (DirEntry[i].DIR_FstClusHI << 16) | DirEntry[i].DIR_FstClusLO;
while (FAT[cluster] != 0xFFF) {cluster = FAT[cluster];
}// 分配新簇
int newCluster = find_free_cluster();
FAT[cluster] = newCluster;
FAT[newCluster] = 0xFFF;  // 文件结束簇// 写入数据
write_to_cluster(newCluster, data, data_size);
DirEntry[i].DIR_FileSize += data_size;
减少文件内容

减少文件内容时,需要以下步骤:

  1. 找到需要保留的最后一个簇:计算文件缩减后的大小,找到需要保留的最后一个簇。
  2. 释放多余簇:在FAT表中释放多余的簇。
  3. 更新目录项:更新文件大小信息。

减少文件内容示例代码:

// 计算缩减后的文件大小和需要保留的簇数
int new_size = DirEntry[i].DIR_FileSize - reduce_size;
int clusters_to_keep = (new_size + BPB_BytsPerSec * BPB_SecPerClus - 1) / (BPB_BytsPerSec * BPB_SecPerClus);// 找到需要保留的最后一个簇
int cluster = (DirEntry[i].DIR_FstClusHI << 16) | DirEntry[i].DIR_FstClusLO;
for (int j = 1; j < clusters_to_keep; j++) {cluster = FAT[cluster];
}// 释放多余的簇
int nextCluster = FAT[cluster];
FAT[cluster] = 0xFFF;  // 文件结束簇
while (nextCluster != 0xFFF) {int temp = FAT[nextCluster];FAT[nextCluster] = 0x0000;  // 标记为空闲nextCluster = temp;
}// 更新目录项
DirEntry[i].DIR_FileSize = new_size;

结语

FAT文件系统由于其简单性和兼容性,仍然在许多领域广泛应用。了解其内部结构和工作原理有助于更好地管理和维护存储设备,同时在需要时也可以进行数据恢复和故障排除。希望这篇博客能够帮助你更好地理解FAT文件系统的运作机制。

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

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

相关文章

DP:回文串模型

一、回文子串 . - 力扣&#xff08;LeetCode&#xff09; 该题有3种解法 &#xff08;1&#xff09;中心扩展算法&#xff08;在字符串章节有介绍&#xff09;时间复杂度O&#xff08;N^2&#xff09;,空间复杂度O&#xff08;1&#xff09; &#xff08;2&#xff09;马丁车…

Spring AI 第二讲 之 Chat Model API 第六节Google VertexAI API

VertexAI API 可提供高质量的定制机器学习模型&#xff0c;只需花费最少的机器学习专业知识和精力。 Spring AI 通过以下客户端提供与 VertexAI API 的集成&#xff1a; VertexAI Gemini Chat Vertex AI Gemini API 允许开发人员使用 Gemini 模型构建生成式人工智能应用程序。…

Apollo9.0 PNC源码学习之Control模块(一)

0 前言 从planning的角度看control&#xff0c;首先需要了解的就是相关的数据接口&#xff0c;规划出的轨迹&#xff08;路径速度&#xff09;发给Control模块去执行 modules/planning/planning_component/planning_component.cc planning模块发布轨迹信息 planning_writer_ …

利用CSS隐藏HTML元素并插入替代内容

在创建一个支持切换阅读模式和答题模式的Anki问答题模板中&#xff0c;我创建了一个支持切换阅读模式和答题模式的问答题模板&#xff0c;该文最终利用JavaScript将Anki输出的向下箭头删除&#xff0c;并插入自定义的提示语。经过进一步测试&#xff0c;发现实现上述功能完全不…

Unity 从0开始编写一个技能编辑器_02_Buff系统的生命周期

工作也有一年了&#xff0c;对技能编辑器也有了一些自己的看法&#xff0c;从刚接触时的惊讶&#xff0c;到大量工作时觉得有一些设计的冗余&#xff0c;在到特殊需求的修改&#xff0c;运行效率低时的优化&#xff0c;技能编辑器在我眼中已经不再是神圣不可攀的存在的&#xf…

【微信小程序】开发环境配置

目录 小程序的标准开发模式&#xff1a; 注册小程序的开发账号 安装开发者工具 下载 设置外观和代理 第一个小程序 -- 创建小程序项目 查看项目效果 第一种&#xff1a;在模拟器上查看项目效果 项目的基本组成结构 小程序代码的构成 app.json文件 project.config…

燃料电池汽车践行者

前言 见《氢燃料电池技术综述》 见《燃料电池工作原理详解》 见《燃料电池发电系统详解》 见《燃料电池电动汽车详解》 见《氢燃料电池汽车行业发展》 现代汽车&#xff08;中国&#xff09; 现代汽车集团&#xff0c;自1998年成立氢燃料电池研发小组以来深耕氢燃料电池技术&am…

html+CSS+js部分基础运用19

1. 应用动态props传递数据&#xff0c;输出影片的图片、名称和描述等信息【要求使用props】&#xff0c;效果图如下&#xff1a; 2.在页面中定义一个按钮和一行文本&#xff0c;通过单击按钮实现放大文本的功能。【要求使用$emit()】 代码可以截图或者复制黏贴放置在“实验…

spring-data-mongodb版本兼容问题

spring-data-mongodb与mongodb驱动有兼容性问题&#xff0c;不匹配会报NoSuchMethod异常&#xff0c;mongodb的java驱动包在4.0之后由mongodb-java-driver更名为mongodb-driver-sync。 spring-data-mongodb包依赖中有mongodb-driver-core&#xff0c;但缺诸如MongoCollection等…

【C语言】文件操作(终卷)

前言 我们在上一卷中了解了顺序读写的函数&#xff0c;现在就让我们从随机读写的函数开始吧。 什么是随机读写&#xff1f; 就是想在哪个位置读或写都行&#xff0c;比较自由。文件打开时光标默认在起始位置。想从后面的某个部分读或写&#xff0c;就得让文件指针来到那个位…

VMware Fusion 如何增加linux硬盘空间并成功挂载

文章目录 0. 前言1. 增加硬盘空间2. 硬盘分区2.1 查看硬盘2.2 分区2.3 格式化2.4 挂载 3. 参考 0. 前言 如果发现虚拟机分配的硬盘不足&#xff0c;需要增加硬盘空间。本文教给大家如何增加硬盘空间并成功挂载。 查看当前硬盘使用情况&#xff1a; df -h可以看到&#xff0c…

什么是档案数字化管理

档案数字化管理指的是将传统的纸质档案转换为数字形式&#xff0c;并通过电子设备、软件和网络技术进行管理和存储的过程。 档案数字化管理包括以下几个步骤&#xff1a; 1. 扫描和数字化&#xff1a;将纸质档案通过扫描仪转换为数字图像或文档。可以使用OCR&#xff08;光学字…

SD 使用教程

SD 换脸步骤 使用Stable Diffusion (SD) 进行换脸的基本步骤可以从以下几个方面概述&#xff0c;这里以一种常见的方式为例&#xff0c;结合了插件的使用来简化流程&#xff1a; 准备工作 安装必要的软件和插件&#xff1a;首先&#xff0c;确保你已经安装了Stable Diffusion…

QT 信号和槽 解除关联示例 disconnect

对于源端的信号和接收端的槽函数&#xff0c;不仅可以进行关联&#xff0c;在关联之后&#xff0c;如果不需要用到它们的关联关系了&#xff0c;可以使用 disconnect 函数解除之前的关联关系。disconnect 函数就是 connect 函数的逆向过程&#xff0c;它们二者的参数是差不多的…

ubuntu24安装python2

下载python2 wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz 解压python2 sudo tar xzf Python-2.7.9.tgz 安装python2 sudo ./configure --enable-optimizations sudo make altinstall 创建快捷方式&#xff08;随便选择一种&#xff09; sudo ln -sfn…

Qt QStackedWidget类详细分析

一.定义 QStackedWidget类是一个容器控件&#xff0c;它提供了一个堆叠的页面布局方式&#xff0c;每个页面可以包含一个子部件。在QStackedWidget中&#xff0c;只有当前活动的页面是可见的&#xff0c;其他页面会被隐藏起来。 QStackedWidget类的常用方法包括&#xff1a; a…

[数据集][图像分类]人种黄种人白人黑人分类数据集970张4类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;970 分类类别数&#xff1a;4 类别名称:[“Asian”,“Caucasian”,“Indian…

什么是 AOF 重写?AOF 重写机制的流程是什么?

引言&#xff1a;在Redis中&#xff0c;持久化是确保数据持久性和可恢复性的重要机制之一。除了常见的RDB&#xff08;Redis Database&#xff09;持久化方式外&#xff0c;AOF&#xff08;Append Only File&#xff09;也是一种常用的持久化方式。AOF持久化通过记录Redis服务器…

01 基础知识

1、Git 的使用 Git 在工作中常用,是必学的东西。请参考下面 pdf 教程搭建环境,并尝试维护一个自己的 github: 下面 git 常用命令,应对 90% 以上工作需求: git clone //从服务器拉取代码 git config //配置开发者用户名和邮箱 git branch //创建、…

自然语言处理(NLP)—— 自动摘要

自动摘要是一种将长文本信息浓缩为短文本的技术&#xff0c;旨在保留原文的主要信息和意义。 1 自动摘要的第一种方法 它的第一种方法是基于理解的&#xff0c;受认知科学和人工智能的启发。 在这个方法中&#xff0c;我们首先建立文本的语义表示&#xff0c;这可以理解为文本…