FAT32文件系统学习(1) —— BPB的理解

2023-11-15

FAT 32 文件系统学习

 

1、本文的目标

       本文将通过实际读取一个FAT32格式的U盘来简单了解和学习FAT32文件系统的格式。虽然目前windwos操作系统的主流文件系统格式是NTFS,但是FAT32由于其兼容性原因,还是有一定的学习价值。为了能做出一个窗体程序提供直观的感觉,本文的代码采用c#编写,对应的c++代码也会附上。

2、本文目录

1、本文的目标

2、什么是FAT32

2.1 FAT32的构成

3、引导区

3.1 读取引导扇区

3.2 BPB参数

3.3 程序实现

2、什么是FAT32

      FAT32是Windwos系统硬盘格式分区的一种。这种格式采用32位的文件分配表,使其对磁盘的管理能力大大增强,突破了FAT16对配一个分区的容量只有2GB的限制。虽然目前已被更优异的NTFS分区格式所取代[1]。其实说白了就是FAT表的每一项长度都是32位,所以叫做FAT32。至于每一项存放的内容是什么,下面的内容会慢慢进行分析。

  • FAT32的构成

       FAT32 文件系统将逻辑盘的空间划分为三部分,依次是引导区 (BOOT区)文件分配表区(FAT区)数据区(DATA区)[2]。引导区和文件分配表区又合称为系统区。本文将简单学习引导区的内容,文件分配表区和数据区将在下一篇文章中学习。

 3、引导区

  • 读取引导扇区

       引导区从第一扇区开始,保存了每个扇区的字节数,一个簇的扇区数,FAT表的起始位置,FAT表的个数以及FAT表的扇区数等信息。之后还留有若干保留扇区。首先我们先看一下如何从一个U盘当中读取引导区(这里只读取第一个扇区,接下来的读取方法相同)。为了直接读取磁盘的逻辑扇区,我们需要用到windows api当中的几个函数,分别是CreateFile(这里用来创建磁盘的句柄),ReadFile(这里用于读取磁盘扇区)。首先来看一下这两个函数的定义:

1 HANDLE WINAPI CreateFile(
2   _In_      LPCTSTR lpFileName,                          // 要打开的文件的名或设备名。
3   _In_      DWORD dwDesiredAccess,                       // 指定类型的访问对象。
4   _In_      DWORD dwShareMode,                           // 文件共享模式
5   _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // 定义了文件的安全特性
6   _In_      DWORD dwCreationDisposition, 
7   _In_      DWORD dwFlagsAndAttributes, 
8   _In_opt_  HANDLE hTemplateFile                         // 返回句柄
9 );

       这个函数在msdn上可以查到,这里需要说明一下的是,dwShareMode需要指定为FILE_SHARE_WRITE才能读取扇区的数据(这里是为什么我也不太清楚为什么,希望高人指教)。dwCreationDisposition需要制定为OPEN_EXISTING ,表示文件必须已经存在,由设备提出要求。函数如执行成功,则返回文件句柄。否则返回的句柄 = INVALID_HANDLE_VALUE表示出错,会设置GetLastError。具体失败原因可以查询ErrorCode。

       第二个函数是ReadFile,其定义如下:

1 BOOL ReadFile(
2     HANDLE hFile,               //文件的句柄
3     LPVOIDl pBuffer,            //用于保存读入数据的一个缓冲区
4     DWORD nNumberOfBytesToRead, //要读入的字节数
5     LPDWORD lpNumberOfBytesRead,//指向实际读取字节数的指针
6     LPOVERLAPPED lpOverlapped
7     //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参  数引用一个特殊的结构。
8     //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL
9 );

       该函数用于读取文件,这里指的是读取U盘扇区。其中lpOverlapped设为NULL即可。需要特别注意的是,由于磁盘是以扇区为单位进行读写的,所以这里读取的字节数必须是512的倍数!其他参数注释写的很明白,这里就不再解释了。配合SetFilePointer函数可以读取指定起始位置上指定字节的数据。

       首先先来看一下用c++是如何读取引导扇区的数据的。

 1     // 笔者的U盘盘符为G
 2     WCHAR szDiscFile[] = _T("\\\\.\\G:"); 
 3     // 打开设备句柄
 4     HANDLE hDisc = CreateFile(szDiscFile, GENERIC_READ,  FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 5     if (hDisc == INVALID_HANDLE_VALUE)
 6     {
 7         // 打开设备失败
 8         return 0;
 9     }
10     // 从第一个扇区起始位置开始读取
11     SetFilePointer(hDisc, 0, 0, FILE_BEGIN);
12     // 需要读取字节数
13     DWORD dwNumber2Read = 512;
14     // 实际读取的字节数
15     DWORD dwRealNumber;
16     // 分配缓冲区
17     char* buffer = new char[512];
18     bool bRet = ReadFile(hDisc, buffer, dwNumber2Read, &dwRealNumber, NULL);
19 
20     // 扫尾工作,释放缓冲区,关闭句柄
21     delete[] buffer;
22     CloseHandle(hDisc);

        如果我们在21行处下各断点的话可以看到buffer在内存中的数据,这里为了方便,笔者直接把这512个字节的数据保存到了文件中,用二进制文件读取软件打开来看了下,部分数据如下图所示:

  • BPB参数

       好了,接下来重点来了。首先,最开始的3各字节的数据分别是跳转指令空指令,因为在汇编当中0xEB是跳转指令,0x58是跳转的地址,而0x90则是空指令。至于为什么要在这里放上一句跳转指令呢,这个还得从启动区开始讲起,为了节约篇幅,我就简单介绍一下:一般第一个扇区叫做启动区,cpu把扇区当中的数据当作指令来执行,当读取到EB 58 这个指令时,遍跳转到0x58这个地址并继续读取指令来执行,而0x58地址之后的内容通常都是载入操作系统的指令。如果希望知道详细内容的读者不妨去看一下《30天自制操作系统》这本书,第一天结尾部分有很详细的说明。总之这边的话FAT32规定这个3各字节的内容必须是EB 58 90,只要记住就行了(笑)。(如1L所说,EB 58 90 对应汇编代码即为JUMP 0x58; NOP;)。

       而从0x03~0x0A这8个字节的数据表示OEM,这里即为“MSDOS5.0”。

       我们把从0x000B开始的79个字节的数据叫做BPB(BIOS Paramter Block),关于BPB的详细说明请参见下表[5]

BPB参数信息
偏移量 字节数 含义
0x00B 2 每扇区字数 0x0200
0x00D 1 每簇扇区数 0x08
0x00E 2 保留扇区数 0x03F8
0x010 1 FAT个数 0x02
0x011 2 根目录项数,FAT32以突破该限制,无效  0x0000 
0x013 2 扇区总数,小于32M使用  0x0000 
0x015 1 存储介质描述负  0x0F8 
0x016 2 每FAT表占用扇区数 ,小于32M使用 0x0000 
0x018 2 逻辑每磁道扇区数  0x003F 
0x01A 2 逻辑磁头数  0x00FF
0x01C 4 系统隐含扇区数  0x00000080
0x020 4 扇区总数,大于32M使用  0x00784F80
0x024 4 每FAT表扇区数,大于32M使用  0x00001E04 
0x028 2 标记  0x0000
0x02A 2 版本 (通常为零) 0x0000
0x02C 4 根目录起始簇  0x00000002 
0x030 2 Boot占用扇区数  0x0001 
0x032 2 备份引导扇区位置  0x0006
0x034 14 保留 14个字节的0x00 
0x042 1 扩展引导标记  0x29 
0x043 4 序列号  0x6A9C4125 
0x047 10 卷标 转成字符即“NO NAME”
0x052 8 文件系统  转成字符即“FAT32” 

 

        我来解释一下其中的几个参数。首先是保留扇区数,它可以理解为是FAT表的起始位置。我们可以先来看一下下面这张图,有助于更好的理解保留扇区数的意思。

       可以看到引导扇区后面紧跟这若干保留扇区,至于保留扇区的作用会在下一篇中分析,这里先跳过。而保留扇区的后面紧跟着的是FAT1和FAT2。所以FAT1表的起始地址是(引导扇区+保留扇区)*扇区字节数?不对。这里有个需要注意的地方是,保留扇区数这个参数其实已经包含了引导扇区了,所以在计算FAT1表位置的时候直接通过保留扇区数这个参数来计算偏移就行了。这一点需要特别注意。(这里笔者看了几篇文献的说法不一,有说需要加上保留扇区的,有说不用加的,可能是版本不一样的关系。但是笔者亲自实践之后发现是不需要加上的。)

       至于FAT表留到下一篇再讲,这里说明一下为什么FAT会有两张。文件分配表区共保存了两个相同的文件分配表,因为文件所占用的存储空间(簇链)及空闲空间的管理都是通过FAT实现的,FAT如此重要,保存两个以便第一个损坏时,还有第二个可用[4]。这样FAT表个数这个参数也解释了。

  • 程序实现

        为了用窗体程序直观的显示各个参数,接下来把上面的程序改写为c#。众所周知,c#调用系统函数大多都需要靠间接调用c的动态库来实现,这里的CreateFile和ReadFile也不例外。下面我们先编写一个FileReader类来提供这些系统api调用。部分代码如下,完整的FileReader点我下载

class FileReader
{
  [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
    static extern unsafe System.IntPtr CreateFile
    (
        string FileName,          // file name
        uint DesiredAccess,       // access mode
        uint ShareMode,           // share mode
        uint SecurityAttributes,  // Security Attributes
        uint CreationDisposition, // how to create
        uint FlagsAndAttributes,  // file attributes
        int hTemplateFile         // handle to template file
    );
  public bool Open(string FileName) { // open the existing file for reading handle = CreateFile ( FileName, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0 ); if (handle != System.IntPtr.Zero) { return true; } else { return false; } }

        由于本文的重点不是学习c#窗体编程,所以略过这部分,直接通过调用FileReader提供的系统API并编写窗体程序,效果如下图所示(本程序参考[3]),需要完整工程的读者可以点我下载,请我VS2012及以上打开。

       好了,今天这篇文章就先写到这边。由于笔者才疏学浅,对于FAT32也是刚开始学习,如果有错误的地方欢迎批评指正。同时这也是我第一次发随笔,如果排版等方面有不妥的地方也欢迎提出。接下来会继续学习接下去的FAT表区和数据区并继续更新接下来的学习心得。

 

参考文献:

1、http://baike.baidu.com/view/45233.htm?fr=aladdin

2、FAT32文件格式 http://blog.csdn.net/shrekmu/article/details/5950414

3、读写U盘(FAT32)引导扇区 http://blog.csdn.net/zhanglei8893/article/details/5912903

4、F​A​T​3​2​文​件​系​统​格​式​详​解 http://wenku.baidu.com/link?url=zrGv8nld-bc-7KT_TKbo2vWplaiIHhmJ9_ydRZBZdZ4zy8odQFwS6komz2gz1AHX36T_EN1CKZ_16d19upW9pDauno6zEmpw10wlTSTwcoi

5、基​于​U​盘​F​A​T​3​2​文​件​系​统​的​分​析 http://wenku.baidu.com/link?url=cIKgrwV66y4CoyuOEB1-OhjRY9tnXtIAoZuYEwDCjxbyRomSIiJgBAXGxq6LudfwuopUpYhiVd8TjxrBFoVyPs0NX3OqbnoWjyn4ZAx60Wi

转载于:https://www.cnblogs.com/fantacity/p/3895771.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FAT32文件系统学习(1) —— BPB的理解 的相关文章

  • 17.subplot():绘制网格区域中的几何形状相同的子区布局

    文章目录 1 函数subplot 的使用方法 2 在极坐标轴上绘制折线图 3 在极坐标轴上绘制散点图 4 在非等分画布的绘图区域上实现图形展示 subplot C R P 表示在C行R列的网格布局上 子区subplot 会被放置到第p个位置
  • 如何用Python提升未来竞争力?十年工作经验老程序员来告诉你。一般人我都不告诉他

    今年很多人在问一个问题 到底什么才是抗风险能力 稳定的工作 存款 理财 有人预测 到2030年 今天一半的工作岗位都将消失 关于哪些工作最先消失 李开复提出过 五秒钟准则 一项工作如果可以在5秒钟内作出相应决定 那就非常可能被人工智能取代
  • 【iOS】【最新】2023苹果开发者账号注册流程(公司类型)

    一 Apple Developer 申请开发者账号 Apple Developer 点击 Account 创建 Apple ID 最好新注册一个新的 专门用做开发 需要注意的是 开发者的名字和 ID 想好在填写 注册成功后 不能自己修改 需
  • Netty网络编程(一):初步了解

    文章目录 简介 netty介绍 netty的第一个服务器 netty的第一个客户端 运行服务器和客户端 总结 简介 我们常用浏览器来访问web页面得到相关的信息 通常来说使用的都是HTTP或者HTTPS协议 这些协议的本质上都是IO 客户端
  • Javaweb的request请求

    1请求数据 request getMethod 获取请求方法 request getContextPath 获取虚拟路径 request getRequestURI 获取url String类型 request getRequestURL
  • Linux环境下安装Hadoop(完全分布式)

    切换到安装目录 解压Hadoop压缩包 修改软件名称 hadoop配置 切换目录 将以下配置文件放在usr app hadoop2 7 3 etc hadoop 目录下 这里 的文件是老师配好的 配置hadoop环境 让hadoop环境配置
  • msvcp120.dll丢失的解决方法?哪种解决方法比较推荐?

    关于msvcp120 dll丢失的解决方法这个问题 小编最近也经常看到有人在提问 可能这是一个比较容易丢失的文件 小编就来给大家详细的分析一下 说说它的三种解决方法 方便大家以后遇到这种问题 自己知道怎么处理 msvcp120 dll丢失的
  • mc服务器server文件夹位置,MC server.properties文件详解

    注 这里true为开启 false为关闭 Minecraft server properties 标题注释 Wed Sep 05 19 27 44 CST 2018 保存时间 spawn protection 16 设置为0将不会禁用出生点
  • Innovus/Encounter时序报告解读

    最近在学report timing这个命令 发现自己对timing report的认知只停留在看slack和delay数值上 于是 决定研究一下这个report Innovus Encounter的report格式确实有点不按套路出牌 初看
  • Es中索引的删除操作

    package com atguigu es test import org apache http HttpHost import org elasticsearch action admin indices delete DeleteI
  • Unity Android 安装apk后显示两个app的问题

    简介 前些天使用Unity打Android包的时候 安装到手机上 出现了两个icon一样的引用 分别点开后 启动的application不一致 原因 在项目中接入了一些SDK SDK的AndroidManifest文件中有个Applicat
  • webpack之引入css

    前言 本文演示了如何打包css文件 涉及到的loader css loader style loader css loader的任务 把css文件作为模块打包 style loader的任务 把打包好的css文件动态的插入到html文件的
  • js中获取token的函数

    1 从cookies获取 从Cookies中获取token function getToken var strcookie document cookie 获取cookie字符串 var arrcookie strcookie split
  • 功能安全专题之功能安全概念阶段

    目录 前言 1 基本概念 1 1 相关项定义 Item Definition 1 2 相关项的构成 1 3 危害分析与风险识别 Hazard Analysis Risk Assessment 1 4 危害与危害事件 Hazard and H
  • Mysql进阶四:常见函数-流程控制函数

    进阶四 流程控制函数 作者 alicomon 寄语读者 博客为学习记录 目的有二 记录知识点 方便温故知新 为读者提供帮助 用于交流 共同提高 流程控制函数 可好玩了 1 if函数 if else 函数 SELECT IF 10 gt 5
  • k8s之三、pod 生命周期/ 探针/ 调度策略/ 副本ReplicaSet / 控制器Deployment

    pod 生命周期官方文档 https kubernetes io zh cn docs concepts workloads pods pod lifecycle 一 容器初始化 创建当前pod容器前 先创建 依赖的其他 container
  • python打包后打开闪退问题解决方法总结

    最近写了一个python项目 今天打包后却发现没有反应 查了一些资料说在程序最后加一个input输入语句可以停留在这里 查看看到报错原因 我加了input语句之后执行下面指令进行打包 pyinstaller F hidden import
  • 整型有哪几种形式?各种形式有什么区别?

    整型有哪几种形式 C 中提供的整数类型有三种 int long short 每种类型又分为有符号和无符号两种类型 有符号整数既可以表示非负整数 又可以表示负整数 但是 无符号整数不能表示负数 只能表示非负整数 一 无符号整数 在内存中 in
  • 素数环

    昨天晚上 突然想读刘汝佳老师书中的例题 素数环 但是突然自己就有了思路 于是便自己实现了一下 但是 由于昨晚时间比较晚 程序是写完了 但是没调试出来 今天一大早就开始调试 花了半小时终于调试出来了 好开心 中心思想是 回溯 上代码 incl
  • sqli-labs布尔盲注和时间盲注相结合的脚本实现

    import time import requests 定义一个变量 用于存放cookie值 HEADER cookie Idea 69a0360c 059291e0 9967 4fe4 bb5e 2524cdcf69d4 security

随机推荐

  • 多元共进|探索社区故事,助力开发者成长

    技术社区中的多元交流 带来丰富的灵感思维 为开发者的发展成长注入不竭的动力 谷歌凭借多种开发者生态项目和社区活动 辅助开发者在学习和成长的道路上稳步前行 中国的开发市场目前正处于全球视野中的重要位置 与各地的开发者交流互动也成为了中国开发者
  • 利用leapmotion实现抓取一个立方体

    1 基础设置 2 拖进来LeapHandController 显示为蓝色 其中 Edit Time Pose选择的是不同的模式 是桌面模式还是VR模式 3 拖进来HandModels 此部分为手势模型 为新建空物体 然后加上Hand Mod
  • 关于visual studio中的$(ConfigurationName)疑问

    关于visual studio中的 ConfigurationName 疑问 2012 12 02 16 09 15 转载 标签 it 分类 程序员之路 关于vs中的各种路径的值de查看方法 来源 http social msdn micr
  • Python---三大流程控制

    三大流程控制语句 1 顺序 按顺序去执行步骤 是最基本的代码执行规则 不做过多的解释 2 分支 单分支 if 条件 满足条件做什么 双分支 if 条件 满足条件做什么 else 不满足条件做什么 三元运算符 双份支的简化版 result 满
  • 关于scanf和printf的一些问题&&EOF和~的问题

    1 scanf和printf的返回值 在C语言中 scanf和printf这两个函数是标准输入输出库中的函数 它们在使用时不返回具体的值 而是通过输入输出参数来完成相应的功能 scanf函数 scanf函数用于从标准输入读取数据并根据提供的
  • KNN 原理及参数总结

    文章目录 前言 1 KNN 原理 2 KNN 优缺点 3 KNN 算法三要素 4 KNN 算法实现 5 sklearn实现KNN算法 前言 针对一个完整的机器学习框架目前还没有总结出来 所以目前只能总结每一个单独的算法 由于现在研究的重点是
  • 详解虚短、虚断以及在运算放大器中的应用

    详解虚短 虚断以及在运算放大器中的应用 一 运算放大器 运算放大器 后续简称运放 是一种集成电路 内部有很多三极管类晶体管的组合 外围接很少的电子元器件就能够实现放大信号的作用 并且信号干净 漂亮 1 1 开环 闭环 运算放大器电路 开环电
  • 2021年新版-编程基础训练32题-附提示和答案

    2021年新版 编程基础训练32题 附提示和答案 1 用级数法求圆周率 题目 圆周率十分重要 不仅仅是在数学理论上 即便在千年前的古代 工程上的需求 也迫切需要我们知道圆周率的尽量精确的数值 求圆周率 有很多种方法 级数法就是简便易行的方法
  • 牛客网Python篇入门编程习题

    目 录 一 输入输出 二 类型转换 三 字符类型 四 列表类型 五 运算符号 六 条件语句 七 循环语句 八 元组类型 九 字典类型 十 内置函数 十一 面向对象 十二 正则表达 本文题库非常适合刚刚接触Python编程的同学 有兴趣的同学
  • STlink V2 烧录器使用教学 【STM32篇】

    STlink V2 是一款支持STM32 STM8 烧录的常规工具 本帖主要讲解STM32 的烧录过程 STM32有2种烧录接口 分别为古老的Jtag接口和目前最常规的SWD接口 由于SWD只需要4条线就能烧录 目前STM32硬件工程师用S
  • Unity使用C#实现简单Scoket连接及服务端与客户端通讯

    简介 网络编程是个很有意思的事情 偶然翻出来很久之前刚开始看Socket的时候写的一个实例 贴出来吧 Unity中实现简单的Socket连接 c 中提供了丰富的API 直接上代码 服务端代码 Thread connectThread 当前服
  • idea 编码扫描插件_4款好用的IDEA插件

    刚开始安装使用的IDEA是没有灵魂的 所以我们要通过插件来给 它注入灵魂 Codota 这是一款代码提示工具 根据你敲击的代码进行提示 这样再敲一些长代码时会方便很多 安装方法 点击file gt settings 选择plugins 搜索
  • 悟空CRM9从零开始搭建详细步骤——肯定成功

    悟空CRM9从零开始搭建详细步骤 欢迎留言 欢迎各位一起加入开源 愿意共享分享学习经验 特别感谢打赏点赞的朋友 我们一起努力分享更多学习经验吧 可参考其他论坛 码云https gitee com wukongcrm 72crm java 悟
  • 用户态--fork函数创建进程

    我们一般使用Shell命令行来启动一个程序 其中首先是创建一个子进程 但是由于Shell命令行程序比较复杂 为了便于理解 我们简化了Shell命令行程序 用如下一小段代码来看怎样在用户态创建一个子进程 include
  • 网上经常看到的冒泡排序的动图如何制作

    今天博主想要和大家分享如何实现动态图 经常在其他博主的文章中可以看到各式各样的动图 搜索一下 网上冒泡排序的动图怎么制作出来 可以看到 很迷 全是告诉冒泡排序的原理 以及动图解析 并没有告知动图是如何制作的 结合博主目前正在学习的前端技术
  • Linux Ubuntu16.04 安装lmdb问题

    LMDB的全称是Lightning Memory Mapped Database 快如闪电的内存映射数据库 它的文件结构简单 包含一个数据文件和一个锁文件 LMDB文件可以同时由多个进程打开 具有极高的数据存取速度 访问简单 不需要运行单独
  • ubuntu下新建txt文档的快捷方式

    进入模板文件夹 Templates 右键打开终端 输入如下命令 sudo gedit txt文档 txt 点击右上角保存 退出 即可通过右键新建txt模板
  • Spring Cache缓存注解

    目录 Spring Cache缓存注解 Cacheable 键生成器 CachePut CacheEvict Caching CacheConfig Spring Cache缓存注解 本篇文章代码示例在Spring Cache简单实现上的代
  • 单片机蓝桥杯——DS1302

    1 原理 对 DS1302的操作就是对其内部寄存器的操作 DS1302内部共有12个寄存器 其中有 7 个寄存器与日历 时钟相关 存放的数据位为 BCD 码形式 此外 DS1302 还有年份寄存器 控制寄存器 充电寄存器 时钟突发寄存器 及
  • FAT32文件系统学习(1) —— BPB的理解

    FAT 32 文件系统学习 1 本文的目标 本文将通过实际读取一个FAT32格式的U盘来简单了解和学习FAT32文件系统的格式 虽然目前windwos操作系统的主流文件系统格式是NTFS 但是FAT32由于其兼容性原因 还是有一定的学习价值