文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构,即在存储设备上组织文件的方法。如果没有文件系统,那我们想找到在硬盘上保存的数据会是一件很麻烦的事情,文件系统的作用是,它负责为用户建立文件、读出、修改,控制文件的读取,我们常说的格式化硬盘就是写入文件系统。文件系统的种类有很多,而且有各自的特点,本文主要介绍FAT32文件系统。
FAT32文件系统由DBR及其保留扇区,FAT1,FAT2和DATA四个部分组成(下图MBR是主引导记录,不一定每个磁盘都有)
MBR主要存储磁盘分区相关的信息,如果存在MBR的话,那么它占用第一个扇区的512个字节,前446个字节为MBR启动代码(这里不关心),接下来16*4个字节为磁盘分区表,每个分区的信息要占16个字节,所以,MBR分区表最多只能保存4个分区的分区信息,最后两个字节是结束标识0x55AA。
如果你的SD卡开头是EB 58 90那就说明你的SD卡没有MBR,需要重新创建MBR,创建过程可以参考SD卡移植FAT32文件系统无MBR,下面我们来看下MBR的内容:
标识 | 长度 | 介绍 | 值 |
---|---|---|---|
Active | 1字节 | 0x80表示活动分区,0x00表示非活动分区 | 0x80 |
StartHead | 1字节 | 分区的开始磁头 | 0x20 |
StartCylSect | 2字节 | 开始柱面与扇区(柱面和扇区分别占用不同位数,有需要查资料) | 0x21 0x00 |
PartType | 1字节 | 分区类型(0x0b和0x0c都是FAT32) | 0x0c |
EndHead | 1字节 | 分区的结束磁头 | 0xFE |
EndCylSect | 2字节 | 结束柱面与扇区(柱面和扇区分别占用不同位数,有需要查资料) | 0xff 0xE1 |
StartLBA | 4字节 | 分区的第一个扇区 | 0x00 0x08 0x00 0x00 |
Size | 4字节 | 分区总扇区数目 | 0x00 0xc0 0xf3 0x00 |
上面显示的是小端模式(地址值存放低字节)
这么多信息,对于初学着只需要知道分区的第一个扇区和分区的大小即可,从上面可以看出起始扇区为0x00000800(注意是小端模式!!)=2048扇区,总扇区数目为0x00f3c000,那么总大小为0xf3c000*512/1024/1024/1024=7.6G
注:
(1)MBR分区方案中,有三种类型的分区,主分区、扩展分区和逻辑分区。扩展分区与逻辑分区是为了突破分区表中只能保存4个分区的限制而出现的。扩展分区不能直接使用,需要在扩展分区内划分一个或多个逻辑分区后才能使用。
(2)一般每个扇区的容量是512字节,4个字节的扇区能表示的最大容量是2TB(2^32 * 512/1024/1024/1024=2048G=2TB),由此可知,在MBR分区表中,分区的起始位置不能大于2TB,分区的最大容量,也不能大于2TB。所以,对2TB以上容量的物理硬盘,不适合使用MBR分区方案。
有一些硬盘厂商,尝试扩大扇区的大小,来突破MBR不适合2TB容量以上的硬盘这一限制。所以有时你会发现市场上存在的硬盘,不完全是每个扇区512字节的,有1024字节甚至2048字节每扇区的。但扩大扇区的大小,又会带来很多其他的问题,特别是会严重影响硬盘的速度,所以这种方法,没有被广泛接受。
DBR是我们格式化分区时创建的,每个分区都会有DBR信息,1个DBR只能定义1个分区的系统文件,占用512个字节
从上面的MBR可知第一个分区在2048扇区(2048*512字节=0x100000)我们直接跳过去看看:
跳转指令:EB 58 90:本身占2字节它将程序执行流程跳转到引导程序处
OEM代号:这部分占8字节,其内容由创建该文件系统的OEM厂商具体安排。
跳转指令之后是8字节长的OEM ID,它是一个字符串, OEM ID标识了格式化该分区的操作系统的名称和版本号。为了保留与MS-DOS的兼容性,通常Windows 2000格式化该盘是在FAT16和FAT32磁盘上的该字段中记录了“MSDOS 5.0”,在NTFS磁盘上(关于ntfs,另述),Windows 2000记录的是“NTFS”。通常在被Windows 95格式化的磁盘上OEM ID字段出现“MSWIN4.0”,在被Windows 95 OSR2和Windows 98格式化的磁盘上OEM ID字段出现“MSWIN4.1”。
BPB:下面是从上图截下的BPB内容
我们主要关注红色字体标出的内容:
标识 | 长度 | 介绍 | 值 |
---|---|---|---|
BytesPerSec | 2字节 | 每扇区字节数,通常为512、1024、2048、4096 | 0x00 0x02 |
SecPerClus | 1字节 | 每簇扇区数,这个值不能为0,而且必须是2的整数次方,比如1、2、4、8、16、32、64、128 | 0x08 |
ResdSecCnt | 2字节 | 保留扇区数 | 0x5E 0x06 |
NumFATs | 1字节 | FAT表数目 | 0x02 |
RootEntCnt | 2字节 | FAT32固定为0 | 0x00 0x00 |
TotSec16 | 2字节 | FAT32固定为0 | 0x00 0x00 |
Media | 1字节 | 存储介质,0xF8标准值,可移动存储介质 | 0xf8 |
FATSz16 | 2字节 | FAT32固定为0 | 0x00 0x00 |
SecPerTrk | 2字节 | 磁道扇区数 | 0x3f 0x00 |
NumHeads | 2字节 | 磁头数 | 0xff 0x00 |
HiddSec | 4字节 | FAT区前隐藏扇区数 | 0x00 0x08 0x00 0x00 |
TotSec32 | 4字节 | 总扇区数 | 0x00 0xC0 0xF3 0x00 |
FATSz32 | 4字节 | 一个FAT表扇区数 | 0xd1 0x3c 0x00 0x00 |
ExtFlags | 2字节 | FAT32持有 | 0x00 0x00 |
FSVer | 2字节 | FAT32持有 | 0x00 0x00 |
RootClus | 4字节 | 第一个目录的簇号 | 0x02 0x00 0x00 0x00 |
FSInfo | 2字节 | 保留扇区数,FSINFO(文件系统信息扇区)扇区号是1,该扇区为操作系统提供关于空簇总数及下一可用簇的信息 | 0x01 0x00 |
BkBootSec | 2字节 | 通常为6 | 0x06 0x00 |
Reserved | 12字节 | 用以扩展 | 0x00 0x00 … 0x00 |
DrvNum | 1字节 | 驱动器号 | 0x80 |
Reserved1 | 1字节 | 保留 | 0x00 |
BootSig | 1字节 | 扩展引导标签 | 0x29 |
VolID | 4字节 | 分区序列 | 0x24 0x09 0x88 0x8a |
FileSysType | 11字节 | 卷标 | 略 |
FilSysType1 | 8字节 | 系统ID | 略 |
解读:
(1)从上面我们可以看出每扇区字节数为0x0200,即512字节
(2)每簇扇区数为0x08
(3)保留扇区数为:0x065e=1630
(4)FAT表数目为2
(5)总扇区为:0x00f3c000即15974400个扇区
(6)一个fat表扇区数:0x000003cd1即15569
(7)第一个目录簇号0x00000002
(8)第一个fat表的扇区号=DBR所在扇区+保留扇区=2048+1630=3678
(9)第一个目录的扇区号=第一个fat表的扇区号+2*(一个fat表扇区数)=3678+2*15569=34816
FAT32文件系统在DBR的保留扇区中安排了一个文件系统信息扇区,用以记录数据区中空闲簇的数量及下一个空闲簇的簇号,该扇区一般在分区的1号扇区,也就是紧跟着DBR后的一个扇区,其内容如下
引导程序代码:FAT32的DBR引导程序占用420字节,对于没有安装操作系统的分区来说这段程序是没有用处的.
结束标识:DBR的结束标志与MBR,EBR的结束标志相同,为“55 AA”。
文件系统分配磁盘空间按簇来分配。因此,文件占有磁盘空间时,基本单位不是字节而是簇,即使某个文件只有一个字节,操作系统也会给它分配一个最小单元:即一个簇。对于大文件,需要分配多个簇。同一个文件的数据并不一定完整地存放在磁盘中一个连续地区域内,而往往会分若干段,像链子一样存放。这种存储方式称为文件的链式存储。为了实现文件的链式存储,文件系统必须准确地记录哪些簇已经被文件占用,还必须为每个已经占用的簇指明存储后继的下一个簇的簇号,对于文件的最后一簇,则要指明本簇无后继簇。这些都是由FAT表来保存的,FAT 表对应表项中记录着它所代表的簇的有关信息:诸如是空,是不是坏簇,是否是已经是某个文件的尾簇等。
定位FAT绝对位置的方法如下:
1、首先从MBR的分区表中得知分区的起始扇区,偏移到此扇区。
2、从DBR的BPB中得知DBR的保留扇区数,FAT表的个数,FAT表的大小。
3、因此FAT1=分区起始扇区+DBR保留扇区,FAT2=分区起始扇区+DBR保留扇区+FAT1。
从上面我们计算出第一个fat表的扇区号在3678扇区,第一个目录的扇区号34816,我们使用winhex查看一下:
第0号表项:0x0FFFFFF8,表示FAT表固定标识
第1号表项:0xFFFFFFFF,不用,默认值
第2号表项:0x0FFFFFFF,根目录所在簇,由于此时只占用1簇,所以是结束标识
下面我们在SD卡里创建一个大于4k(每簇占8个扇区即4k,只有大于4k才占用多簇)文件,重新查看该位置的内容
此时已经看到新增加了三簇内容:该test文件簇链为0x05—>0x06–>0x07(结束),注意簇链结束标识为0x0FFFFFFF,文件大小小于一簇大小的直接占用1簇,以0X0FFFFFFF结束
数据区时真正用于存放用户数据的区域,数据区的位置在FAT2的后面,具体定位方式如下;
1、通过MBR中的分区表信息得知分区的起始位置。
2、通过分区中DBR得知DBR的保留扇区数以及FAT表的大小,FAT表的个数。
3、通过上面的信息就可以找到数据区的起始位置,数据区 = 隐藏扇区数+DBR保留扇区+(每个FAT表扇区数*2)。
数据区的类容主要由三部分组成:根目录,子目录和文件内容。在数据区中是以“簇”为单位进行存储的,2号簇被分配给根目录使用。
数据起始扇区=根目录起始扇区号+(簇号-2)x每簇的扇区数
注:FAT表对所有划分后的位置由0进行地址编号。0号地址与1号地址被系统保留并存储特殊标志内容。从2号地址开始,每个地址对应于数据区的簇号,也就是数据区起始位第2簇!FAT表中0和1号表项没有对应物理地址。
前面我们算出第一个目录(根目录)的扇区号34816,我们使用winhex直接跳转34816过去看下:
FAT32文件系统中,分区根目录下的文件和目录都放在根目录区中,子目录中的文件和目录都放在子目录区中,并且每32个字节为一个目录项(FDT),每个目录项纪录着一个目录或文件(也可能是多个目录项记录一个文件或目录),上图所示就是一个目录项。
在FAT32文件系统中,目录项可以分为四类:卷标目录项、“.”和“…”目录项、短文件名目录项、长文件名目录项。
我们分别创建SHUIYUE目录和SHUIYUE.txt文件来看下
FDT第1字节又表明了该文件的状态,它有如下四种取值方式:
a. 00H–目录项的空目录。
b. E5H–表示该目录项曾经使用过,但文件已被删除。
c. 2EH–表示子目录下的两个特殊文件 “. “或 “… “目录项
d. 其它任何字符–表示一个文件名(或目录名)的第一个字符的ASCII码值.
我们来看下SHUIYUE.txt目录项代表的东西
标识 | 长度 | 介绍 | 值 |
---|---|---|---|
deName | 8字节 | 文件名,不足部分补空格(0x20) | 0x53 0x48 0x55 0x49 0x59 0x55 0x45 0x20(SHUIYUE) |
deExtension | 3字节 | 扩展名,不足部分补空格(0x20) | 0x54 0x58 0x54(TXT) |
deAttributes | 1字节 | 文件属性 | 0x20(存档) |
deLowerCase | 1字节 | 系统保留 | 0x10 |
deCTime | 3字节 | 创建时间 | 0x8c 0x00 0xab |
deCDate | 2字节 | 创建日期 | 0x8d 0x51 |
deADate | 2字节 | 最后访问的日期 | 0x8d 0x51 |
deHighClust | 2字节 | 开始簇的高两个字节 | 0x00 0x00 |
deMTime | 2字节 | 最后修改的时间 | 0x09 0xab |
deMDate | 2字节 | 最后修改的日期 | 0x8d 0x51 |
deLowCluster | 2字节 | 开始簇的低两个字节 | 0x06 0x00 |
deFileSize | 4字节 | 文件的大小 | 0xd8 0x21 0x00 0x00 |
从上面我们可以看出SHUIYUE.txt开始簇为0x06我们查找FAT表:
从第6簇开始,占据了3簇,我们跳到第6簇看下内容,第6簇在数据区起始扇区34816+(6-2)*8=34848
从上可以看出刚好是我们写入的数据,其他可以自己尝试,例如新创建一个不同大小的文件、创建子目录观察数据的变化。
注:
(1)目录所在的扇区,都是以32 Bytes划分为一个单位,每个单位称为一个目录项。
(2)根据文件名及后缀,我们可以分为短目录文件,长目录文件,简单点理解,如果文件名>8 byte 或者后缀名>3, 则为长文件目录,否则为短文件目录
参考文章:
(1)FAT32长文件名短文件名目录项
(2)详解FAT32文件系统
(3)FAT32文件系统格式详解
(4)FAT32文件系统详解
(5)SD卡中FAT32文件格式快速入门(详细图文介绍)
(6)FAT32文件系统SD卡建立MBR引导扇区
(7)FAT32文件系统格式详解(图文针对具体文件存储,分析fat32 SD卡)
(8)MBR、EBR与DBR详解
本文章仅供学习交流用禁止用作商业用途,文中内容来水枂编辑,如需转载请告知,谢谢合作
微信公众号:zhjj0729
文章浏览阅读1.8k次,点赞4次,收藏6次。python简易爬虫v1.0作者:William Ma (the_CoderWM)进阶python的首秀,大部分童鞋肯定是做个简单的爬虫吧,众所周知,爬虫需要各种各样的第三方库,例如scrapy, bs4, requests, urllib3等等。此处,我们先从最简单的爬虫开始。首先,我们需要安装两个第三方库:requests和bs4。在cmd中输入以下代码:pip install requestspip install bs4等安装成功后,就可以进入pycharm来写爬虫了。爬
文章浏览阅读2.6k次。解决方法:解决方法可以去github重新下载一个pyflakes.vim。执行如下命令git clone --recursive git://github.com/kevinw/pyflakes-vim.git然后进入git克降目录,./pyflakes-vim/ftplugin,通过如下命令将python目录下的所有文件复制到~/.vim/ftplugin目录下即可。cp -R ...._freetorn.vim
文章浏览阅读210次,点赞7次,收藏3次。本文简述了hello.c源程序的预处理、编译、汇编、链接和运行的主要过程,以及hello程序的进程管理、存储管理与I/O管理,通过hello.c这一程序周期的描述,对程序的编译、加载、运行有了初步的了解。_hit csapp
文章浏览阅读1w次,点赞2次,收藏27次。来源:机器人小妹 很多时候企业拥有重复,乏味且困难的工作流程,这些流程往往会减慢生产速度并增加运营成本。为了降低生产成本,企业别无选择,只能自动化某些功能以降低生产成本。 通过数字化..._人工智能平台
文章浏览阅读2.2k次。热加载能够在每次保存修改的代码后自动刷新 electron 应用界面,而不必每次去手动操作重新运行,这极大的提升了开发效率。安装 electron 热加载插件热加载虽然很方便,但是不是每个 electron 项目必须的,所以想要舒服的开发 electron 就只能给 electron 项目单独的安装热加载插件[electron-reloader]:// 在项目的根目录下安装 electron-reloader,国内建议使用 cnpm 代替 npmnpm install electron-relo._electron-reloader
文章浏览阅读942次。在11.0 进行定制化开发,会根据需要去掉recovery模式的一些选项 就是在device.cpp去掉一些选项就可以了。_android recovery 删除 部分菜单
文章浏览阅读2.2k次,点赞2次,收藏6次。继续上次的echart博客,由于省会流向图是从echart画廊中直接取来的。所以直接上代码<!DOCTYPE html><html><head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /&_java+echart地图+物流跟踪
文章浏览阅读1.4k次。一、OSD模块简介1.1 消息封装:在OSD上发送和接收信息。cluster_messenger -与其它OSDs和monitors沟通client_messenger -与客户端沟通1.2 消息调度:Dispatcher类,主要负责消息分类1.3 工作队列:1.3.1 OpWQ: 处理ops(从客户端)和sub ops(从其他的OSD)。运行在op_tp线程池。1...._ceph 发送数据到其他副本的源码
文章浏览阅读7.9k次,点赞3次,收藏22次。一 定义这是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。该算法实现简单,只需把一个进程已调入内存的页面,按先后次序链接成一个队列,并设置一个指针,称为替换指针,使它总是指向最老的页面。但该算法与进程实际运行的规律不相适应,因为在进程中,有些页面经常被访问,比如,含有全局变量、常用函数、例程等的页面,FIFO 算法并不能保证这些页面不被淘汰。这里,我_进程调度fifo算法代码
文章浏览阅读133次。rownum是oracle才有的写法,rownum在oracle中可以用于取第一条数据,或者批量写数据时限定批量写的数量等mysql取第一条数据写法SELECT * FROM t order by id LIMIT 1;oracle取第一条数据写法SELECT * FROM t where rownum =1 order by id;ok,上面是mysql和oracle取第一条数据的写法对比,不过..._mysql 替换@rownum的写法
文章浏览阅读790次,点赞3次,收藏4次。官网下载下载链接:http://www.eclipse.org/downloads/点击Download下载完成后双击运行我选择第2个,看自己需要(我选择企业级应用,如果只是单纯学习java选第一个就行)进入下一步后选择jre和安装路径修改jvm/jre的时候也可以选择本地的(点后面的文件夹进去),但是我们没有11版本的,所以还是用他的吧选择接受安装中安装过程中如果有其他界面弹出就点accept就行..._ecjelm
文章浏览阅读245次。原文链接:https://linux.cn/article-7801-1.htmlifconfigping <IP地址>:发送ICMP echo消息到某个主机traceroute <IP地址>:用于跟踪IP包的路由路由:netstat -r: 打印路由表route add :添加静态路由路径routed:控制动态路由的BSD守护程序。运行RIP路由协议gat..._ifconfig 删除vlan