C++的课,老师把数据和机组和C++都串连起来了,好棒!
讲动态变量,讲到new和malloc,delete和free,它们的相似与不同;
FAT的原理我大概听到的是:有这样一个表格,存储要访问数据的地址,有了首地址,就可以依照链表的结构去依次查询到下一个数据的地址,进而去磁盘上访问。
于是不禁产生一些疑问出来,那这样的表格是动态生成的喽?还是说第一次访问时动态地生成表格,后面再要访问,就依照第一次生成的这个表格去访问磁盘,这样就能够提高访问磁盘的效率?哦,难道是在往磁盘里存数据的时候,就已经把这么一个表格生成并且还保存了,第一次访问,就已经是按照这个表格来的?恩,这样似乎还能想得通~
自己去上网查找了FAT的资料,太复杂了,看不大懂诶!只好先就这样想喽~
附:
文件配置表(英文:File Allocation Table,首字母缩略字:FAT)是一种由微软发明的并带有部分专
利[1]的文件系统,供MS-DOS使用,也是非NT内核的微软窗口使用的文件系统。 FAT文件系统考虑当时计算机效能有限,所以未被复杂化,因而被几乎所有个人计算机的操作系统支持。这特性使它成为理想的软盘和记忆卡文件系统,也适合用作不同操作系统中的数据交流。 但FAT有一个严重的缺点:当文件被删除并且在同一位置被写入新数据,他们的片段通常是分散的,减慢了读写速度。磁盘碎片重整是一种解决方法,但必须经常重组来保持FAT文件系统的效率。 FAT的缺点还有以下几点: 1.大磁盘浪费空间 2.磁盘利用效率低 3.文件存储受限制 4.不支持长文件名,只能支持8个字符。 5.安全性较差
设计
[编辑]主磁盘结构
主启动区 | 文档 分配表#1 | 文档 分配表#2 | 根目录 | 其他所有数据... 剩下磁盘空间 |
一个FAT文件系统包括四个不同的部分。
- 保留扇区,位于最开始的位置。第一个保留扇区是引导区(分区启动记录)。它包括一个称为基本输入输出参数块的区域(包括一些基本的文件系统信息尤其是它的类型和其它指向其它扇区的指针),通常包括操作系统的启动调用代码。保留扇区的总数记录在引导扇区中的一个参数中。引导扇区中的重要信息可以被DOS和OS/2中称为驱动器参数块的操作系统结构访问。
- FAT区域。它包含有两份文档分配表,这是出于系统冗余考虑,尽管它很少使用,即使是磁盘修复工具也很少使用它。它是分区信息的映射表,指示簇是如何存储的。
- 根目录区域。它是在根目录中存储文档和目录信息的目录表。在FAT32下它可以存在分区中的任何位置,但是在早期的版本中它永远紧随FAT区域之后。
- 数据区域。这是实际的文档和目录数据存储的区域,它占据了分区的绝大部分。通过简单地在FAT中添加文档链接的个数可以任意增加文档大小和子目录个数(只要有空簇存在)。然而需要注意的是每个簇只能被一个文档占有,这样的话如果在32KB大小的簇中有一个1KB大小的文档,那么31KB的空间就浪费掉了。
[编辑]启动扇区
格式如下
偏移(字节) | 长度(字节) | 说明 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | 3 | 跳转指令(跳过开头一段区域) | ||||||||||||||||
0x03 | 8 | OEM名称(空格补齐)。MS-DOS检查这个区域以确定使用启动记录中的哪一部分数据 [3] 。常见值是IBM 3.3 (在“IBM”和“3.3”之间有两个空格)和MSDOS5.0 . | ||||||||||||||||
0x0b | 2 | 每个扇区的字节数。基本输入输出系统参数块从这里开始。 | ||||||||||||||||
0x0d | 1 | 每簇扇区数 | ||||||||||||||||
0x0e | 2 | 保留扇区数(包括启动扇区) | ||||||||||||||||
0x10 | 1 | 文档分配表数目 | ||||||||||||||||
0x11 | 2 | 最大根目录条目个数 | ||||||||||||||||
0x13 | 2 | 总扇区数(如果是0,就使用偏移0x20处的4字节值) | ||||||||||||||||
0x15 | 1 | 介质描述
同样的介质描述必须在重复复制到每份FAT的第一个字节。有些操作系统(MSX-DOS 1.0版)全部忽略启动扇区参数,而仅仅使用FAT的第一个字节的介质描述确定文件系统参数。 | ||||||||||||||||
0x16 | 2 | 每个文档分配表的扇区(FAT16) | ||||||||||||||||
0x18 | 2 | 每磁道的扇区 | ||||||||||||||||
0x1a | 2 | 磁头数 | ||||||||||||||||
0x1c | 4 | 隐藏扇区 | ||||||||||||||||
0x20 | 4 | 总扇区数(如果超过65535,参见偏移0x13) | ||||||||||||||||
0x24 | 4 | 每个文档分配表的扇区(FAT32)。扩展基本输入输出系统参数块从这里开始。 | ||||||||||||||||
0x24 | 1 | 物理驱动器个数(FAT16) | ||||||||||||||||
0x25 | 1 | 当前磁头(FAT16) | ||||||||||||||||
0x26 | 1 | 签名(FAT16) | ||||||||||||||||
0x27 | 4 | ID(FAT16) | ||||||||||||||||
0x28 | 2 | Flags(FAT32) | ||||||||||||||||
0x2a | 2 | 版本号(FAT32) | ||||||||||||||||
0x2c | 4 | 根目录启始簇(FAT32) | ||||||||||||||||
0x2b | 11 | 卷标(非FAT32) | ||||||||||||||||
0x30 | 2 | FSInfo扇区(FAT32) | ||||||||||||||||
0x32 | 2 | 启动扇区备份(FAT32) | ||||||||||||||||
0x34 | 12 | 保留未使用(FAT32) | ||||||||||||||||
0x36 | 8 | FAT文件系统类型(如FAT、FAT12、FAT16) | ||||||||||||||||
0x3e | 2 | 操作系统自引导代码 | ||||||||||||||||
0x40 | 1 | BIOS设备代号(FAT32) | ||||||||||||||||
0x41 | 1 | 未使用(FAT32) | ||||||||||||||||
0x42 | 1 | 标记(FAT32) | ||||||||||||||||
0x43 | 4 | 卷序号(FAT32) | ||||||||||||||||
0x47 | 11 | 卷标(FAT32) | ||||||||||||||||
0x52 | 8 | FAT文件系统类型(FAT32) | ||||||||||||||||
0x1FE | 2 | 扇区结束符(0x55 0xAA) |
这里描述的启动扇区能在如OS/2 1.3的启动盘上看到。早期的版本使用一个较短的基本输入输出系统参数块,它们的启动代码在前面开始(如OS/2 1.1中是偏移0x2b)。
[编辑]例外情况
Apricot PC的MS-DOS所用FAT的实现有一个不同的启动扇区组织以使用计算机与IBM不兼容的基本输入输出系统。跳转指令和OEM名被省略并且MS-DOS文件系统参数位于0x50(在标准扇区中偏移为0x0B - 0x17)。后来的Apricot MS-DOS版本除了Apricot特有的引导区之外也具有了读写标准启动分区的能力。
BBC Master 512上的DOS Plus根本就不使用传统的引导区。数据磁盘省略了引导区并且以一个单份的FAT开始(FAT的第一个字节用来确定磁盘容量),启动磁盘使用一个包含启动调用程序的小型ADFS文件系统,后面跟随一个单份的FAT。
[编辑]文档分配表
一个分区分成同等大小的簇,也就是连续空间的小块。簇的大小随着FAT文件系统的类型以及分区大小而不同,典型的簇大小介于2KB到32KB之间。每个文档根据它的大小可能占有一个或者多个簇;这样,一个文档就由这些这些(称为单链表)簇链所表示。然而,这些链并不一定一个接着一个在磁盘上存储,它们经常是在整个数据区域零散的储存。
文档分配表(FAT)是映射到分区每个簇的条目列表。每个条目记录下面五种信息中的一种。
- 链中下一个簇的地址
- 一个特殊的文档结束符(EOF)符号指示链的结束
- 一个特殊的符号标示坏簇
- 一个特殊的符号标示保留簇
- 0来表示空闲簇
每个版本的FAT文件系统使用不同大小的FAT条目。这个大小已经由名字表示出来,例如FAT16文件系统的每个条目使用16位表示,32位文件系统使用32位表示。这个不同意味着FAT32系统的文档分配表能比FAT16映射更多的簇,它也允许FAT32有更大的分区大小。这也使得FAT32比FAT16更能有效地利用磁盘空间,因为每个驱动器能够寻址更小的簇,这也就意味着更少的空间浪费。
FAT条目值:
FAT12 | FAT16 | FAT32 | 描述 |
---|---|---|---|
0x000 | 0x0000 | 0x?0000000 | 空闲簇 |
0x001 | 0x0001 | 0x?0000001 | 保留簇 |
0x002 - 0xFEF | 0x0002 - 0xFFEF | 0x?0000002 - 0x?FFFFFEF | 被占用的簇;指向下一个簇 |
0xFF0 - 0xFF6 | 0xFFF0 - 0xFFF6 | 0x?FFFFFF0 - 0x?FFFFFF6 | 保留值 |
0xFF7 | 0xFFF7 | 0x?FFFFFF7 | 坏簇 |
0xFF8 - 0xFFF | 0xFFF8 - 0xFFFF | 0x?FFFFFF8 - 0x?FFFFFFF | 文档最后一个簇 |
注意FAT32只使用32位中的28位。高4位通常是0但它们是保留位,不要更改它们。在上面的表中它们用问号表示。
[编辑]目录表
目录表是一个表示目录的特殊类型文档(现今通常称为文件夹)。它里面保存的每个文档或目录使用表中的32位条目表示。每个条目记录名字、扩展名、属性(档案、目录、隐藏、只读、系统和卷)、创建的日期和时间、文档/目录数据第一个簇的地址,最后是文档/目录的大小。
除了FAT12和FAT16文件系统中的根目录表占据特殊的根目录区域位置之外,所有其它的目录表都存在数据区域。
合法的DOS文件名包括下面一些字符:
- 大写字母A-Z
- 数字0-9
- 空格(尽管结尾的空格被作为填充而不是文件名的一部分)
- ! # $ % & ( ) - @ ^ _ ` { } ~ '
- 数值128-255
DOS文件名位于OEM字符集。
位于根目录区域和子目录区域的目录条目都是下面的格式:
字节偏移 | 长度 | 描述 | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x00 | 8 | DOS文件名(附加空格) 第一个字节可以是下面的特殊数值:
| |||||||||||||||||||||||||||
0x08 | 3 | DOS文件扩展名(空格补齐) | |||||||||||||||||||||||||||
0x0b | 1 | 文档属性 第一个字节可以是下面一些特殊值:
属性值0x0F用来表示长文件名条目。 | |||||||||||||||||||||||||||
0x0c | 1 | 保留,NT使用(参见后面) | |||||||||||||||||||||||||||
0x0d | 1 | 创建时间,最小时间分辨率:10ms单位,数值从0到199。 | |||||||||||||||||||||||||||
0x0e | 2 | 创建时间。小时、分钟和秒根据后面的图示描述进行编码:
注意秒只保存了2秒的分辨率。更细分辨率的文档创建时间在偏移0x0d处。 | |||||||||||||||||||||||||||
0x10 | 2 | 创建日期。年、月和日根据后面的图示编码:
| |||||||||||||||||||||||||||
0x12 | 2 | 最近访问时间;参见偏移0x0e处的描述。 | |||||||||||||||||||||||||||
0x14 | 2 | FAT12和FAT16中的EA-Index(OS/2和NT使用),FAT32中第一个簇的两个高字节 | |||||||||||||||||||||||||||
0x16 | 2 | 最后更改时间;参见偏移0x0e处的描述。 | |||||||||||||||||||||||||||
0x18 | 2 | 最后更改日期; 参见偏移0x10处的描述。 | |||||||||||||||||||||||||||
0x1a | 2 | FAT12和FAT16中的第一个簇。FAT32中第一个簇的两个低字节。 | |||||||||||||||||||||||||||
0x1c | 4 | 文档大小 |
长文件名(LFN)使用一个技巧存储在FAT文件系统上——在目录表中添加假的条目。这些条目使用一个普通文档无法使用的卷标属性标识,普通文档无法使用是由于它们被大多数旧的MS-DOS程序忽略。很显然,一个只包含卷标的目录被当作空卷,这样就允许删除;使用长文件名创建的文档在从普通的DOS删除就会发生这样的情形。
校验和也允许检验长文件名是否与8.3文件名匹配;当一个文档删除之后使用DOS在同一个目录位置重新创建之后就会出现不匹配现象。校验和使用下面的算法计算。(注意pFcbName是指向如正常目录条目中所显示的文件名的指针,例如前八个字符是文件名,最后三个是扩展名。点是隐含的。文件名中没有使用的空间将使用空格(ASCII 0x20)补齐。例如,“Readme.txt”将记录为"README TXT"。
unsigned char lfn_checksum (const unsigned char *pFcbName) { int i; unsigned char sum=0; for (i=11; i; i--) sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + *pFcbName++; return sum; }
旧版的PC-DOS错误地将根目录中的长文件名当作卷标,这样它们就会显示错误的卷标。
每个假条目包含13UTF-16个字符(26字节),通过使用包含文档大小或者时间记录的区域获得除了旧的8+3之外的另外15个字节(但是出于安全和磁盘检查工具的考虑开始簇的区域没有使用保留值为0)。参见8.3中另外的解释。
长文件名条目使用下面的格式:
字节偏移 | 长度 | 描述 |
---|---|---|
0x00 | 1 | 串行号 |
0x01 | 10 | 名称字符(5个UTF-16字符) |
0x0b | 1 | 属性(永远是0x0F) |
0x0c | 1 | 保留(永远是0x00) |
0x0d | 1 | DOS文件名校验和 |
0x0e | 12 | 名称字符(6个UTF-16字符) |
0x1a | 2 | 第一个簇(永远是0x0000) |
0x1c | 4 | 名称字符(两个UTF-16字符) |
如果一个文件名只包含小写字母、或者是一个小写字母的名加上大写扩展名的混合或者与此相反,没有特殊的字符并且满足8.3的限制,在视窗NT上就不创建VFAT的条目。相反,在目录条目的偏移0x0c处的没有说明的位用来指示文件名全部或者部分是小写字母。特别明确的是,位4意味着小写字母的扩展名,位3意味着名是小写字母,这样就允许如“example.TXT”和“HELLO.txt”这样的组合,但是不允许“Mixed.txt”这样的组合。很少有操作系统支持这种功能。非NT视窗版本当这个扩展使用时将把文件名当作大写字母。缺省情况下,Linux的最近版本将认识这个扩展但是在写时并不使用它。
[编辑]第三方扩展
在微软公司添加长文件名和创建/访问时间戳之前,其它的操作系统使用目录表字节0x0C-0x15存储其它的元数据。它们包括:
字节偏移 | 长度 | 系统 | 描述 | |||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0C | 2 | RISC OS | 文档类型,0x000 - 0xFFF | |||||||||||||||||||||||||||||||||||||||
0x0C | 1 | DOS Plus | 用户定义文档属性F1-F4
| |||||||||||||||||||||||||||||||||||||||
0x0D | 1 | DR-DOS | 被删除文件名最初第一个字符 | |||||||||||||||||||||||||||||||||||||||
0x0E | 2 | DR-DOS和FlexOS | 加密文档密码 | |||||||||||||||||||||||||||||||||||||||
0x10 | 4 | DR-DOS 7 | 被删除文档最初的文档时间和日期;被删除文档有设置到删除时间的正常时间和日期 | |||||||||||||||||||||||||||||||||||||||
0x12 | 2 | DR-DOS 6和FlexOS | 文档所有者身份 | |||||||||||||||||||||||||||||||||||||||
0x14 | 2 | DR-DOS和FlexOS | 文档许可位(只有FlexOS使用执行许可):
|