分析FAT32内部结构-入门篇-
FAT32(File Allocation Table)是一种32位的FAT文件系统,微软在1996年8月发布。
FAT32的数字32是下面会讲到的FAT中每个表项的长度。
磁盘(硬盘)是数据的载体,而文件系统则是将这些数据以某种合理的结构组织起来方便操作系统的管理。
借此文分析一下微软的FAT32文件系统格式:(本文分析的FAT32分区是D盘,大小为128MB!环境为VMware虚拟机下的XP系统!)
FAT32由4个部分组成,分别是DBR,FAT1,FAT2和DATA,如图:
DBR:该分区的引导程序,在DBR的结尾部分会有一些重要的保留扇区(这些保留扇区属于DBR,图中未画出)
FAT1:FAT的首要文件分配表
FAT2:文件分配表的备份
DATA:数据区(最小单位为簇(cluster),一般2个扇区为1簇,是微软规定的一种磁盘存储单位,与Linux的block概念类似)
FAT32的DBR结构图:
红色:跳转指令,将当前执行流程跳转到引导程序处,占2字节,对应汇编JUMP 58H; NOP;
蓝色:OEM代号,由创建该文件系统的厂商规定,占8字节,一般为”MSDOS5.0”
绿色:BPB(BIOS Paramter Block),从DBR的第12个字节开始共占用79字节,记录了文件系统的重要信息,相关字段参数见下表
粉红色:DBR引导程序,如果该分区没安装操作系统那么这段程序是没用的
黄色:DBR结束标记
BPB表: |
||
偏移 |
字节 |
含义 |
BH |
2 |
每扇区的字节个数 |
DH |
1 |
每簇扇区数 |
EH |
2 |
保留的扇区个数 |
10H |
1 |
FAT个数 |
11H |
2 |
不使用(根目录数量,FAT32已突破此限制,已无效,一般为0) |
13H |
2 |
不使用(扇区总数,小于32M时才使用) |
15H |
1 |
存储介质描述符 |
16H |
2 |
不使用(FAT占的扇区数,小于32M时才使用) |
18H |
2 |
每磁道扇区个数 |
1AH |
2 |
磁头数 |
1CH |
4 |
隐藏扇区 |
20H |
4 |
扇区总数(大于32M时使用) |
24H |
4 |
FAT占的扇区数(大于32M时使用) |
28H |
2 |
扩展标记 |
2AH |
2 |
版本,一般为0 |
2CH |
4 |
根目录的首簇号 |
30H |
2 |
文件系统整体信息扇区号 |
32H |
2 |
DBR备份所在的扇区号 |
34H |
12 |
保留,固定为0 |
40H |
1 |
BIOS驱动器号 |
41H |
1 |
不使用,一般为0 |
42H |
1 |
扩展引导标记 |
43H |
4 |
卷序列号 |
47H |
11 |
卷标 |
52H |
8 |
文件系统类型名,固定为”FAT32 ” |
FAT32文件系统在DBR的保留扇区中有一个文件系统信息扇区,用以记录数据区中空闲簇的数量及下一个空闲簇的簇号,该扇区一般在分区的LAB1扇区,也就是紧跟着DBR后的一个扇区,其内如下:
褐色:扩展引导标签,为52 52 61 41,ASCII为”RRaA”
青色:文件系统信息签名,为72 72 41 61,ASCII为”rrAa”
蓝色:空闲簇的数量,(1FBB0)=129968,每个簇1K,约等于127MB,即D盘的大小
紫色:下一个空闲簇的簇号
黄色:结束标记
其他字节:不使用,填充0
由于FAT紧跟在DBR的保留扇区之后,所以定位到最后一个保留扇区,那么下一个扇区就是FAT啦!
在上面的DBR图中可以找到保留扇区的个数为20H=32(20 00是小端表示法),所以DBR往后32个扇区就是首要FAT啦,如图:
FAT以4字节(32位)为一个表项,每个表项值的含义:
0x0000 0000 |
空闲簇,可用簇 |
0x0000 0001 |
保留簇 |
0x0000 0002 ~ 0x0FFF FFEF |
该簇已用,其值指向下一个簇号 |
0x0FFF FFF0 ~ 0X0FFF FFF6 |
这些值保留,不使用 |
0x0FFF FFF7 |
坏簇,当一个簇中有一个扇区损坏(如物理损坏、病毒感染)时称为坏簇,这个簇将不被FAT32使用 |
0x0FFF FFF8 ~ 0x0FFF FFFF |
文件的最后一个簇 |
每个表项的值对应了相应簇的使用情况,如2号表项对应了2号簇的使用情况,3号表项对应了3号簇的使用情况,注意的是,最开头的两个表项是不使用的,它们代表FAT的表头,其值是固定的0xFFF FFF8和0xFFFF FFFF,所以!FAT32中不存在0号簇和1号簇,第1个簇是2号簇!画张图:
如果该簇是文件的最后一簇,填入的值为0x0FFFFFFF,如果该簇不是文件的最后一簇,则填入的值为该文件占用的下一簇号(所以可以看出在FAT32文件系统中文件是以簇链表的形式保存起来的)。
2号表项存储的是2号簇的使用情况,一般2号簇(也就是文件系统的第1个簇)存储的是文件系统的根目录,虽然在FAT32中,根目录的位置不再硬性固定,可以存储在分区内可寻址的任意簇内,不过通常根目录是最早建立的(格式化时)目录,所以基本上都是根目录首簇紧邻FAT2,占簇区顺序上的第1个簇(即2号簇),同时,FAT32将根目录当做普通的数据文件,所有没有了目录个数的限制,在需要的时候可以分配空簇。这一项(2号表项)的值为0x0FFFFFFF ,说明当前根目录占了1个簇的大小。
现在来分析数据区,数据区是紧接在FAT2之后的,所以在DBR往后(保留扇区+FAT1占用的扇区+FAT2占用的扇区)个扇区就是数据区啦,如图(这是数据区的第一个扇区,也是第一个簇的前半部分):
发现前11字节是我们的卷标!
而在BPB中卷标那项的值永远是”NO NAME ”,也就是说卷标被移动到了数据区的前11字节,而且FAT32卷标最长11字节(因为BPB中已经规定了),而NTFS已经突破了这个限制。
其实,卷标是根目录下的第一个文件!
现在来分析一下FAT32下文件和目录之间是如何组织的,如何存储的,如何保存属性的:
先低级格式化D盘,以确保分区干净(指的是数据区全填充为0),
低级格式化完成(如果分区较大,低格的速度会变慢,耐心等待)之后,查看一个首要FAT表,
有一个表项,它的值为FFF FFFFH,意思就是结束簇,这就是我们的根目录啦,再查看一个根目录所在的起始簇,
发现前两行(32字节)有数据,后面全是0,然后我们在D盘(根目录)下粘贴一个空文件(在其他盘(如C盘)新建一个文本文件,然后复制到D盘,下面会讲为什么不能直接在D盘新建文件,而非要从其他盘复制),
再去首要FAT中查看变化,发现没有变化,看起来新建的文件不占表项,再去根目录所在簇查看一下,
发现!多了2行(32字节),这就是我们刚刚新建(其实是粘贴)的空文件A.TXT啦,现在我们要引入一个FAT32下短文件目录项概念了,来个表格,
字节偏移 |
字节数 |
说明 |
|
0H |
8 |
文件名 |
|
8H |
3 |
后缀名,扩展名,类型名 |
|
BH |
1 |
文件属性 |
0000 0000B, 0H 读写 |
0000 0001B, 1H 只读 |
|||
0000 0010B, 2H 隐藏 |
|||
0000 0100B, 4H 系统 |
|||
0000 1000B, 8H 卷标 |
|||
0001 0000B, 10H 子目录 |
|||
0010 0000B, 20H 归档 |
|||
CH |
1 |
保留 |
|
DH |
1 |
创建时间的10毫秒位 |
|
EH |
2 |
创建时间 |
|
10H |
2 |
创建日期 |
|
12H |
2 |
最后一次访问的日期 |
|
14H |
2 |
起始簇号的高16位 |
|
16H |
2 |
最近一次修改的时间 |
|
18H |
2 |
最近一次修改的日期 |
|
1AH |
2 |
起始簇号的低16位 |
|
1CH |
4 |
文件长度 |
可以看出文件长度为0,起始簇号高16位为0H,低16位也为0H,也就是指向0号簇,但是0号簇不存在,所以此文件不存在起始簇,也就验证了文件长度为0,现在我们用记事本打开此文件,向其中写几个单词,
再来看看此文件的属性,
现在先去看一下首要FAT的变化,
哈哈,多了一个表项哦,这个多的表项的值也是FFF FFFFH,也就是结束簇,我们再去根目录所在簇看看,
发现了没,起始簇号和文件长度都发现了相应的变化,图中给出了计算值,这符合前面用右键查看的A.TXT属性,且起始簇号为3也是正确的,因为簇号2被根目录所占用,那么下一个簇号就是3啦,现在我们去簇号3看看,
现在我们将A.TXT增加到几KB(我从网上找了微软的百度百科复制了其中一段),这里需要注意,因为我这个D盘的簇大小仅仅为1KB,所以大于1KB就可以完成本步骤的实验了,如果你们的簇大小为NKB,那么A.TXT需要大于NKB才行,
然后我们先去根目录查看一下,
数值又发生了变化,但是一定和上图的属性中一样,这里不再计算,然后我们再去首要FAT看一下,
发现,多了6项,且原来的3号表项已经不是FFF FFFFH了,取而代之的是9号表项变成了FFF FFFFH,这样就形成了簇链,文件系统读取时就通过这个单链表读取,我们简单计算一下,A.TXT最多占7个簇(第7个簇恰好全部用完,即占用空间的大小),最少占6个簇(第7个簇只用了1个字节),那么推测出A.TXT大小在[6144+1,7168]字节,而A.TXT在其的属性截图中大小为6546字节,占用空间为7168字节,完全符合,
现在我们来看一下FAT32的长文件目录项格式(现在基本用的都是长文件名啦),
字节偏移 |
字节数 |
说明 |
0H |
1 |
第7位:保留 |
第6位:1表示长文件最后一个目录项 |
||
第5位:保留 |
||
第0~4位:顺序号 |
||
1H |
10 |
Unicode文件名第1部分 |
BH |
1 |
长文件名目录项标志,值默认FH |
CH |
1 |
保留 |
DH |
1 |
校验值(根据短文件名计算) |
EH |
12 |
Unicode文件名第2部分 |
1AH |
2 |
起始簇号 |
1CH |
4 |
Unicode文件名第3部分 |
我们再从其他盘复制过来一个长文件名的空文本文件,
查看一下根目录,
长文件名是以链表方式存储的,所以能存很长很长的文件名,文件名结束符为’\0’,即0H,如果结束符之后还有剩余的Unicode字符则以FFH填充,在长文件目录项的最后两行是它的短目录项存储格式哦,简单说一下为什么长文件目录项第1行第1字节为43H,下图,
至此,简单的FAT32组织结构已经介绍完了,欢迎读者深入探究。
附上,一篇写FAT32不错的博文:https://blog.csdn.net/yangyang031213/article/details/79030247
来说一下为什么上面要复制其他盘的文件到D盘,因为直接在D盘新建一个文本文件是“新建 文本文档.txt”,然后我们将它重名名为“NEW.TXT”,然后在winhex查看,发现还是存在一个“新建 文本文档.txt”的,只不过是删除状态的,所以为了避免这项因素的干扰,我就选择了从其他盘复制文件过来。
附上簇的取值范围表:
分区大小 |
FAT32默认簇大小 |
32~256M |
中间还分多个挡位:512B,1K,2K |
257M~8G |
4K |
8G~16G |
8K |
32G~2T |
32K |
题外话,也算是一个练习,验证网上说的“FAT32最大只能存放4G的文件”:
因为FAT32中目录项中每个文件的文件长度是4字节,4字节最大能寻址的字节数为2的32次,换算为G就是4G啦,即2^32B/1024^3=4G。
分析FAT32内部结构-入门篇-的更多相关文章
- 一个App完成入门篇(七)- 完成发现页面
第七章是入门篇的倒数第二篇文章了,明天整个APP将进入收官. 本节教程主要要教会大家使用二维码扫描和用do_WebView组件加在html页面. 导入项目 do_WebView组件 扫描功能 自定义事 ...
- 转:OSGi 入门篇:生命周期层
OSGi 入门篇:生命周期层 前言 生命周期层在OSGi框架中属于模块层上面的一层,它的运作是建立在模块层的功能之上的.生命周期层一个主要的功能就是让你能够从外部管理应用或者建立能够自我管理的应用(或 ...
- Unity3D大风暴之入门篇(海量教学视频版)
智画互动开发团队 编 ISBN 978-7-121-22242-9 2014年2月出版 定价:79.00元 328页 16开 编辑推荐 长达800分钟的高清教学视频,手把手教会初学者 数个开发案例 ...
- Memcached缓存入门篇
Asp.Net中使用Couchbase——Memcached缓存入门篇 前言 本文的主要目的就是简单的进行使用Memcached.这是Memchahed的官网http://memcached.org/ ...
- 腾讯QQ会员技术团队:人人都可以做深度学习应用:入门篇(下)
四.经典入门demo:识别手写数字(MNIST) 常规的编程入门有"Hello world"程序,而深度学习的入门程序则是MNIST,一个识别28*28像素的图片中的手写数字的程序 ...
- MongoDB索引(一) --- 入门篇:学习使用MongoDB数据库索引
这个系列文章会分为两篇来写: 第一篇:入门篇,学习使用MongoDB数据库索引 第二篇:进阶篇,研究数据库索引原理--B/B+树的基本原理 1. 准备工作 在学习使用MongoDB数据库索引之前,有一 ...
- sed修炼系列(一):花拳绣腿之入门篇
本文为花拳绣腿招式入门篇,主要目的是入门,为看懂sed修炼系列(二):武功心法做准备.虽然是入门篇,只介绍了基本工作机制以及一些选项和命令,但其中仍然包括了很多sed的工作机制细节.对比网上各sed相 ...
- CoreCLR源码探索(七) JIT的工作原理(入门篇)
很多C#的初学者都会有这么一个疑问, .Net程序代码是如何被机器加载执行的? 最简单的解答是, C#会通过编译器(CodeDom, Roslyn)编译成IL代码, 然后CLR(.Net Framew ...
- JMeter性能测试,完整入门篇
1. Jmeter简介 Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件.相比Loadrunner而言,JMeter小巧轻便且免费,也越来越流行成为了主流的性能测试工具 ...
随机推荐
- 「Shimo使用指南」mac支持pptp协议的小软件
Mac的好多小伙伴在访问网络设备时觉得远程连接不方便,例如ssh,***登陆都不是很方便,后来又安装了open*** forMac.ISSH等客户端,使用后发现不是很稳定,断线后很久都无法连接等缺点, ...
- 为什么有的插件安装需要用Vue.use()方法
问题 相信很多人在用Vue使用别人的组件时,会用到 Vue.use() .例如:Vue.use(VueRouter).Vue.use(MintUI).但是用 axios时,就不需要用 Vue.use( ...
- HTML连载53-网易注册界面实战之content的头部、content注册信息
一. 这次完成了content部分的右边图片以及content的top部分的边角填充 <!DOCTYPE html> <html lang="en"> &l ...
- python中list的运算,操作及实例
在操作list的时候,经常用到对列表的操作运算,比如说,列表添加,删除操作,其实,这里面经常回遇到这样一个问题,就是列表的操作容易被混淆了. 有人做了一个总结,这个很清晰,我就不多做阐述了: 1.ap ...
- Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!
本文原题“从实践角度重新理解BIO和NIO”,原文由Object分享,为了更好的内容表现力,收录时有改动. 1.引言 这段时间自己在看一些Java中BIO和NIO之类的东西,也看了很多博客,发现各种关 ...
- Vue 从入门到进阶之路(十三)
之前的文章我们介绍了一下 vue 中的作用域插槽,本章我们来看一下动态组件与 v-once 指令. <!DOCTYPE html> <html lang="en" ...
- netty源码解析(4.0)-27 ByteBuf内存池:PoolArena-PoolThreadCache
前面两章分析的PoolChunk和PoolSubpage,从功能上来说已经可以直接拿来用了.但直接使用这个两个类管理内存在高频分配/释放内存场景下会有性能问题,PoolChunk分配内存时算法复杂度最 ...
- django简单密码加密和效验
通过django自带的类库,来加密解密很方便,下面来简单介绍下: 导入包: from django.contrib.auth.hashers import make_password, check_p ...
- golang-方法和接口
1.方法 方法类似函数 ,多了一个接收者 ,接收者是指针指向结构体(也可以是值) ,方法与结构体绑定 (可以理解为模板定义方法) ,方法位于结构体内部 方法集可以理解就是多个方法 可以组合其他结构体方 ...
- JavaScript 语句解析
在 HTML 中,JavaScript 语句是由 web 浏览器“执行”的“指令”. 实例 var x, y, z; // 语句 1 x = 22; // 语句 2 y = 11; // 语句 3 z ...