注意:本文章最初是翻译自 FatFs 官网的 The basics of FAT filesystem。但是,原文大多都是文字说明,因此在翻译时,添加了大量的图片示例以及一些额外的章节。
因此,以下翻译与原文有很多差别。具体表现为下文中的英文部分全部是原文,没有任何更改;中文部分添加了一些额外内容!
FAT Filesystem FAT文件系统
This is a documentation about FAT filesystem written based on the FAT32 Filesystem Specification (FAT specs below) to know how FAT filesystem works and how to manage it. It is written according to the contents of the FAT specs and the behavior of the standard system (real DOS and Windows), however, there are many improvements and ommissions from the FAT specs. If the behavior of standard system is differ from the FAT specs, it is written in accordance with the real systems rather than FAT specs. And there is a possibility that there is any unintended or intended error in this documentation, so that you need to refer the primary sources of FAT filesystem and make sure behavior of the real systems when write FAT driver or utility. For exFAT filesystem, please refer here in addition to this documentation.
这是一个关于 FAT 文件系统的文档,该文件基于 FAT32 文件系统规范(以下称为 FAT 规范(FAT specs))编写,以了解 FAT 文件系统的工作原理以及如何管理它。 它是根据 FAT 规范的内容和标准系统(实际的 DOS 和 Windows)的行为编写的,因而,相比 FAT 规范有许多改进和省略。 如果标准系统的行为与 FAT 规范不同,则它是根据实际系统而不是 FAT 规范编写的。并且本文档中可能存在任何意外或预期的错误,因此您需要参考 FAT 文件系统的源文件,并在编写 FAT 驱动程序或实用程序时确保实际系统的行为。对于 exFAT 文件系统,除了本文档之外,请参阅此处。
Introduction 简介
The filesystem generally denotes the entire system to manage data on the storage, however, this document describes the data format of FAT filesystem on the storage device.
文件系统通常表示管理存储器上的数据的整个系统,不过,该文档描述了存储设备上的 FAT 文件系统的数据格式。
The FAT file system originated around 1980 and is the filesystem that was first supported by MS-DOS. It was originally developped a simple filesystem suitable for floppy disk less than 500k bytes in size. Over the time, its specs has been expanded to support larger media as increasing its capacity. FAT is the abbreviation of File Allocation Table, which is the array to manage allocation of data area and the name of the file system itself. Currently there are three FAT sub-types, FAT12, FAT16 and FAT32. These are developped in order of the number and completely backward compatible with older one. (FAT16 always include FAT12, FAT32 includes all FAT types)
FAT 文件系统起源于 1980 年左右,是 MS-DOS 首先支持的文件系统。 它最初是为了适用于大小小于 500k 字节的软盘而开发了一个简单的文件系统。 随着时间的推移,其规范已经扩大到支持更大容量的媒介的能力。FAT 是文件分配表(File Allocation Table)的缩写,它是管理数据区域分配和文件系统本身名称的合称。 目前有三种 FAT 子类型,FAT12,FAT16 和 FAT32。它们按数字大小顺序开发,完全向后兼容旧版本。 (FAT16 始终包含 FAT12,FAT32 包括所有 FAT 类型)
About Notations in this Document 关于本文档中的符号
Numbers starting with “0x” are assumed to be hexadecimal numbers, and others are decimal numbers.
以 “0x” 开头的数字假定为十六进制数字,其他数字为十进制数字。
The prefix K, M, G and T of each unit is assumed to be 210, 220, 230 and 240 respectively.
假定每个单位的前缀 K,M,G 和 T 分别为 210, 220, 230 和 240。
The fragment of program codes contained in this document is written assuming C language, but it is not strict to the syntax.
本文档中包含的程序代码片段是假定使用 C 语言编写的,但并不严格符合语法。
32-bit value and 16-bit value are arbitrary mixed in the fragment of the program code. The programmer needs be aware of the data loss due to the type conversion and how to avoid it. Also, every data type is assumed to be unsigned. Do not calculate in signed because it may result in unintended results.
32 位值和 16 位值在程序代码段中任意混合。程序员需要知道由于类型转换而造成的数据丢失以及如何避免它。此外,假定每种数据类型都是无符号的。不要在带符号的情况下计算,因为这可能会导致意想不到的结果
Basics of FAT File System FAT文件系统基础
FAT Volume FAT 卷
A FAT file system completes itself is called logical volume (or logical drive). The FAT logical volume consists of three or four areas, each of them consists of one or more sectors and located on the volume in order of as follows. (FAT volume map)
FAT 文件系统将自身称为逻辑卷(或逻辑驱动器)。 FAT 逻辑卷由三个或四个区域组成,每个区域由一个或多个扇区组成,并按以下顺序位于卷上。 (FAT volume map 即下图。后文的介绍都是基于该图示来说明的)
- Reserved area (volume configuration data) 保留区域(卷配置数据)
- FAT area (allocation table for data area) FAT区域(数据区域的分配表)
- Root directory area (not present on FAT32 volume) 根目录区域(FAT32 卷上不存在)
- Data area (contents of file and directory) 数据区(文件和目录的内容)
Sector 扇区
Sector is the smallest unit of data block on the storage to read and write the storage device. The common sector size is 512 bytes and a larger sector size is sometimes used for some type of storage media. Each sector on the storage device is addressed by a sector number assgined in order from top of the storage device. Since volumes are not that always placed at top of the storage, in this document, “sector number” denotes the relative location origin from top of the volume and “physical sector number” denotes the absolute location origin from top of the storage device.
扇区是存储器上读写存储设备的最小数据块单元。 一般的扇区大小为 512 字节,有时某些类型的存储介质会使用更大的扇区。 存储设备上的每个扇区由从存储设备顶部按顺序分配的扇区号寻址。 由于卷不总是位于存储器的顶部,因此在本文档中,“扇区号” 表示从卷顶部开始的相对位置,“物理扇区号” 表示从存储设备顶部开始的绝对位置。
Data Forms on the Storage 存储器上的数据形式
The FAT file system was initially developed for IBM PC with x86 processors. The most important thing is that data structures in the FAT filesystem on the storage is stored in little endian. If the architecture of the platform to access the FAT filesystem is big endian, an endian conversion is required when accessing the structures of the FAT filesystem. Also, word data in multiple bytes are not that always aligned to the word boundaries. If the processor cannot access the unaligned word data, it will need to access the data in byte-by-byte. For this reason, accessing the FAT volume as C structure member discards the code portability. Accessing the FAT volume in byte-by-byte as simple byte array instead of C structure gives the best code portability.
FAT 文件系统最初是为使用 x86 处理器的 IBM PC 开发的。 最重要的是存储器上的 FAT 文件系统中的数据结构以小端模式存储的。 如果访问 FAT 文件系统的平台的体系结构是大端模式,那么在访问 FAT 文件系统的结构时需要进行字节序转换。 此外,含多个字节的字数据并不总是与字边界对齐的。 如果处理器无法访问未对齐的字数据,则需要逐字节访问数据。 因此,以 C 结构成员的方式访问 FAT 卷会丢弃代码可移植性。 以以字节为单位的简单字节数组而不是 C 结构成员的方式访问 FAT 卷,可提供最佳的代码可移植性。
Boot Sector and BPB 引导扇区和BPB
The most important data structure in the FAT volume is BPB (BIOS Parameter Block), where the configuration parameters of the FAT volume are stored. The BPB is placed in the boot sector. The boot sector is often referred to as VBR (Volume Boot Record) or PBR (Private Boot Record), but it is simply the first sector of the reserved area, the first sector of the volume.
FAT 卷中最重要的数据结构是 BPB(BIOS Parameter Block,BIOS 参数块),其中存储 FAT 卷的配置参数。 BPB 位于引导扇区中。 引导扇区通常称为 VBR(Volume Boot Record,卷引导记录)或 PBR(Private Boot Record,专用引导记录),但它只是保留区域的第一个扇区,即卷的第一个扇区。
BPB has often been changed as the function of the FAT file system is enhanced. The first confusion that occurred was due to the newly-establishment of BPB. In the MS-DOS Ver.1, there was no BPB in the boot sector. In the first version of the FAT file system, there is only a few disk format (single-sided and double-sided 5.25 inch floppy disk), and the disk format is determined by referring to the first byte (lower 8 bits of the first FAT item) of FAT starting at the next sector of the boot sector.
随着 FAT 文件系统功能的增强,BPB 经常被更改。 发生的第一次混乱是由于 BPB 的第一次出现。 在 MS-DOS Ver.1 中,引导扇区中没有 BPB。 在 FAT 文件系统的第一个版本中只有少数磁盘格式(单面和双面 5.25 英寸软盘),并且磁盘格式是通过参考引导扇区的后一个扇区的开始的第一个字节(第一个字节的低 8 位)来确定。
At the MS-DOS Ver.2, this method of determination of disk format is superseded by referring the BPB in the boot sector and the determination by referring the first byte of FAT has not been supported any longer. Now all FAT volumes must have a BPB in the boot sector. BPB was sometimes changed and it brought confusions about determination of disk format. (e.g. Which is the correct parameter? What means this parameter? How should I use this parameter?) The authorized volume recognization method is described in FAT specs a time later.
在 MS-DOS Ver.2 中,确定磁盘格式的方法被通过参考引导扇区中的 BPB 取代,并且不再支持通过参考 FAT 的第一个字节来确定的这种方法。 现在所有 FAT 卷必须在引导扇区中具有 BPB。 BPB 有时会发生变化,并且会对确定磁盘格式的界定产生混淆。 (例如,哪个是正确的参数?这个参数是什么意思?应该如何使用这个参数?)一段时间后,FAT 规范中描述了授权的卷识别方法。
At the first time, problems about deterioration of disk usage efficiency and limitation of the number of files on a volume appered due to the disk size got lager by widespread use of hard disks and FAT16 has newly supported at MS-DOS Ver.3. However, a new problem occurred immediately after this change. Since the size of field to indicating the size of the volume was 16 bits, the supported volume size is less than 65536 sectors (32 MB at 512 bytes/sector). For this reason, a 32-bit field has been added to at MS-DOS Ver.3.31 and it can support 128 MB for FAT12 and 2 GB for FAT16 (at 32 KB/cluster).
随着硬盘的广泛使用,磁盘容量越来越大,第一次出现了磁盘使用效率恶化和卷上文件数量限制的问题。在 MS-DOS Ver.3 中新引入了对 FAT16 的支持。 但是,此更改后立即出现了一个新的问题。 由于指示卷大小的字段大小为 16 位,因此支持的卷大小小于 65536 个扇区(512 字节/扇区为 32 MB)。 因此,在 MS-DOS Ver.3.31 中添加了一个 32 位字段,它可以支持 FAT12 的 128 MB 和 FAT16 的 2 GB( 32 KB/cluster)。
The last change of BPB was at Windows 95 OSR2 where the FAT32 appeared. At that time, number of files and maximum capacity of the FAT16 volume had reached at some applications. The FAT32 as final version of FAT filesystem removed the limitations of FAT16 and spports upto 2 TB of volume size (at 512 bytes/sector). However Microsoft recommends any filesystem other than FAT, such as NTFS for fixed disk and exFAT for removable disk, for the volumes larger than 32 GB.
BPB 的最后一次更改是在 Windows 95 OSR2 上出现了 FAT32 时。 那时,某些应用程序已达到 FAT16 卷的文件数和最大容量。 作为 FAT 文件系统的最终版本的 FAT32 取消了 FAT16 的限制并且支持高达 2TB 的卷大小(512字节/扇区)。 但是,对于大于 32 GB 的卷,Microsoft 建议使用 FAT 以外的其他任何文件系统,例如固定磁盘的 NTFS 和可移动磁盘的 exFAT。
The following table shows the data fields of the boot sector. Any field named with heading BPB_ are part of the BPB. Any field named with heading BS_ is not a part of BPB but it only a part of the boot sector.
下表显示了引导扇区的数据字段。 任何以 BPB_ 开头的字段都是 BPB 内容的一部分。 任何以 BS_ 开头的字段都不是 BPB 的一部分,但它只是引导扇区的一部分。
The fields in the first 36 bytes are common field for all FAT types and the fields from byte offset 36 depends on whether the FAT type is FAT32 or FAT12/FAT16. The method of determining FAT type is described at next section.
前 36 个字节中的字段是所有 FAT 类型的公共字段,36 字节偏移后的字段取决于 FAT 类型是 FAT32 还是 FAT12/FAT16。 确定 FAT 类型的方法在下一节中描述。
FAT12/16/32 common field (offset from 0 to 35)
Field name 字段名 | Offset 偏移 | Size 大小 | Description 描述 |
---|---|---|---|
BS_JmpBoot | 0 | 3 | Jump instruction to the bootstrap code (x86 instruction) used by OS boot sequence. There are two type of formats for this field and the former format is prefered. 操作系统引导序列使用的跳转到引导代码(x86指令)的指令。 该字段有如下的两种格式,优先选择前一种格式。 0xEB, 0x??, 0x90 (Short jump + NOP)0xE9, 0x??, 0x?? (Near jump)?? is the arbitrary value depends on where to jump is. In case of any format out of these formats, the volume will not be recognized by Windows. ?? 表示任意值,取决于跳转的位置。 如果是以上两种格式之外的任何格式,Windows 都将无法识别该卷。 |
BS_OEMName | 3 | 8 | “MSWIN 4.1” is recommended but also “MSDOS 5.0” is often used. There are many misconceptions about this field. This is only a name. Microsoft’s OS does not pay any attention to this field, but some FAT drivers do some reference. This string is recommended because it is considered to minimize compatibility problems. You can set something else, but some FAT drivers may not recognize that volume. This field usually indicates name of the system created the volume. 该字段建议使用值 “MSWIN 4.1”,但也经常使用 “MSDOS 5.0”。 关于这个区域存在许多误解。 这只是一个名字。 微软的操作系统并不关心这个区域,但是一些 FAT 驱动程序会作为一些参考。 建议使用推荐的字符串,因为它被视为最小化兼容性问题。 您可以设置成其他值,但某些 FAT 驱动程序可能无法识别该卷。 此字段通常表示创建该卷的系统的名称。 |
BPB_BytsPerSec | 11 | 2 | Sector size in unit of byte. Valid values for this field are 512, 1024, 2048 or 4096. Microsoft’s OS properly supports these sector sizes, but many FAT drivers assume the sector size is 512 and do not check this field. For this reason, 512 should be used for maximum compatibility. However, you should not misunderstand that it is only related to compatibility. This value must be the same as the sector size of the storage contains the FAT volume. 扇区大小,以字节为单位。 此字段的有效值为 512, 1024, 2048 或 4096。Microsoft 的操作系统正确支持这些扇区大小,但许多 FAT 驱动程序假定扇区大小为 512 并且不检查此字段。 因此,应使用 512 以实现最大兼容性。 但是,您不应该误解它只与兼容性有关。 此值必须与包含 FAT 卷的存储的扇区大小相同。 |
BPB_SecPerClus | 13 | 1 | Number of sectors per allocation unit. In the FAT file system, the allocation unit is called Cluster. This is a block of one or more consecutive sectors and the data area is managed in this unit. The number of sectors per cluster must be a power of 2. Therefore, valid values are 1, 2, 4,… and 128. However, any value whose cluster size (BPB_BytsPerSec * BPB_SecPerClus) exceeds 32 KB should not be used. Recent systems, such as Windows, supprts cluster size larger than 32 KB, such as 64 KB, 128 KB, and 256 KB, but such volumes will not be recognized correctly by MS-DOS or old disk utilities. 每个分配单元的扇区数。 在 FAT 文件系统中,分配单元称为簇(Cluster)。 这是一个由一个或多个连续扇区的组成的块,并且数据区域在该单元中进行管理。 每个簇的扇区数必须是 2 的幂。因此,幂有效值为 1,2,4,…和 128。但是,不应使用其簇大小( BPB_BytsPerSec * BPB_SecPerClus )超过 32 KB 的任何值。 较新的系统(如Windows)支持大小超过 32 KB 的簇大小,例如 64 KB,128 KB 和 256 KB,但 MS-DOS 或旧磁盘实用程序无法正确识别此类卷。 |
BPB_RsvdSecCnt | 14 | 2 | Number of sectors in reserved area. This field must not be 0 because there is the boot sector itself contains this BPB in the reserved area. To avoid compatibility problems, it should be 1 on FAT12/16 volume. This is because some old FAT drivers ignore this field and assume that the size of reserved area is 1. On the FAT32 volume, it is typically 32. Microsoft’s OS properly supports any value of 1 or larger. 保留区域的扇区数。 该字段不能为 0,因为包含 BPB 的引导扇区本身就位于保留区域中。 为避免兼容性问题,FAT12/16 卷应为 1。 这是因为一些旧的 FAT 驱动程序忽略此字段并假设保留区域的大小为 1。在 FAT32 卷上,它通常为 32。Microsoft 的操作系统正确支持 1 或更大的任何值。 |
BPB_NumFATs | 16 | 1 | Number of FATs. The value of this field should always be 2. Also any value eaual to or greater than 1 is valid but it is strongly recommended not to use values other than 2 to avoid compatibility problem. Microsoft’s FAT driver properly supports the values other than 2 but some tools and FAT drivers ignore this field and operate with number of FAT is 2. FAT 的数量。 此字段的值应始终为 2。此外,任何等于或大于 1 的值都有效,但强烈建议不要使用 2 以外的值以避免兼容性问题。 Microsoft 的 FAT 驱动程序正确支持 2 以外的值,但某些工具和 FAT 驱动程序忽略此字段并且将 FAT 的数量当做 2 来处理。 The standard value for this field 2 is to provide redudancy for the FAT data. The value of FAT entry is typically read from the first FAT and any change to the FAT entry is refrected to each FATs. If a sector in the FAT area is damaged, the data will not be lost because it is duplicated in another FAT. Therefore it can minimize risk of data loss. On the non-disk based storages, such as memory card, such redundancy is a useless feature, so that it may be 1 to save the disk space. But some FAT driver may not recognize such a volume properly. 该字段的标准值 2 ,用以为 FAT 数据提供一个冗余的备份。 通常从第一个 FAT 读取 FAT 条目的值,并且对 FAT 条目的任何更改都会重新映射到每个 FAT。 如果 FAT 区域中的扇区损坏,则数据不会丢失,因为它在另一个 FAT 中重复。 因此,它可以将数据丢失的风险降至最低。在诸如存储卡之类的非基于磁盘的存储器上,这种冗余是无用的特征,因此可以是 1 以节省磁盘空间。 但是一些 FAT 驱动程序可能无法正确识别这样的卷。 |
BPB_RootEntCnt | 17 | 2 | On the FAT12/16 volumes, this field indicates number of 32-byte directory entries in the root directory. The value should be set a value that the size of root directory is aligned to the 2-sector boundary, BPB_RootEntCnt * 32 becomes even multiple of BPB_BytsPerSec. For maximum compatibility, this field should be set to 512 on the FAT16 volume. For FAT32 volumes, this field must be 0. 在 FAT12/16 卷上,此字段指示根目录中 32 字节的目录条目的数量。 该值应设置为根目录的大小与 2 扇区边界对齐的值, BPB_RootEntCnt * 32 甚至变为 BPB_BytsPerSec 的倍数。 为获得最大兼容性,FAT16 卷上的此字段应设置为 512。 对于 FAT32 卷,此字段必须为 0。 |
BPB_TotSec16 | 19 | 2 | Total number of sectors of the volume in old 16-bit field. This value is the number of sectors including all four areas of the volume. When the number of sectors of the FAT12/16 volumes is 0x10000 or larger, an invalid value 0 is set in this field, and the true value is set to BPB_TotSec32. For FAT32 volumes, this field must always be 0. 旧 16 位字段中卷的扇区总数。该值是包括卷的所有四个区域在内的扇区总数。 当 FAT12/16 卷的扇区数为 0x10000 或更大时,在该字段中应设置为无效值 0,并将实际值设置到 BPB_TotSec32 字段中。 对于 FAT32 卷,此字段必须始终为 0。 |
BPB_Media | 21 | 1 | The valid values for this field is 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE and 0xFF. 0xF8 is the standard value for non-removable disks and 0xF0 is often used for non partitioned removable disks. Other important point is that the same value must be put in the lower 8-bits of FAT[0]. This comes from the media determination of MS-DOS Ver.1 and not used for any purpose any longer. 该字段的有效值为 0xF0,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE 和 0xFF 之一。 0xF8 是不可移动磁盘的标准值,0xF0 通常用于非分区可移动磁盘。 其他重要的一点是必须将相同的值放在 FAT[0] 的低 8 位中。 这来自 MS-DOS Ver.1 的媒体确定,不再用于任何目的。 |
BPB_FATSz16 | 22 | 2 | Number of sectors occupied by a FAT. This field is used for only FAT12/16 volumes. On the FAT32 volumes, it must be an invalid value 0 and BPB_FATSz32 is used instead. The size of the FAT area becomes BPB_FATSz?? * BPB_NumFATs sectors. FAT 占用的扇区数。 该字段仅用于 FAT12/16 卷。 在 FAT32 卷上,它必须是无效值 0,而是使用 BPB_FATSz32 字段。 FAT 区域的大小变为 BPB_FATSz ?? * BPB_NumFATs 个扇区。(注:?? 在 FAT12/16 中是 16,在 FAT32 中是 32) |
BPB_SecPerTrk | 24 | 2 | Number of sectors per track. This field is relevant only for media that have geometry and used for only disk BIOS of IBM PC. 每个轨道的扇区数。 此字段仅适用于具有几何体且仅用于 IBM PC 的磁盘 BIOS 的介质。 |
BPB_NumHeads | 26 | 2 | Number of heads. This field is relevant only for media that have geometry and used for only disk BIOS of IBM PC. 头数。 此字段仅适用于具有几何体且仅用于 IBM PC 的磁盘 BIOS 的介质。 |
BPB_HiddSec | 28 | 4 | Number of hidden physical sectors preceding the FAT volume. It is generally related to storage accessed by disk BIOS of IBM PC, and what kind of value is set is platform dependent. This field should always be 0 if the volume starts at the beginning of the storage, e.g. non-partitioned disks, such as floppy disk. FAT 卷之前隐藏的物理扇区数。 它通常与 IBM PC 的磁盘 BIOS 访问的存储有关,设置的值与平台有关。 如果卷从存储器的开头开始,则该字段应始终为 0,例如, 非分区磁盘,例如软盘。 |
BPB_TotSec32 | 32 | 4 | Total number of sectors of the FAT volume in new 32-bit field. This value is the number of sectors including all four areas of the volume. When the value on the FAT12/16 volume is less than 0x10000, this field must be invalid value 0 and the true value is set to BPB_TotSec16. On the FAT32 volume, this field is always valid and old field is not used. 新 32 位字段中 FAT 卷的扇区总数。 该值是包括卷的所有四个区域在内的扇区总数。 当 FAT12/16 卷上的值小于 0x10000 时,该字段必须是无效值 0,并且将实际值设置到 BPB_TotSec16 中。 在 FAT32 卷上,此字段始终有效,不使用旧字段。 |
Since the following fields change depending on whether the volume is FAT12/16 or FAT32, the FAT type must be determined prior to refer these fields. Also there are some fields exist in only FAT32 volumes and not exist in FAT12/16 volumes.
由于以下字段根据卷是 FAT12/16 还是 FAT32 而变化,因此必须在引用这些字段之前确定 FAT 类型。 还有一些字段仅存在于 FAT32 卷中,而不存在于 FAT12/16 卷中。
Fields for FAT12/16 volumes (offset from 36) FAT12/16 卷字段(从 36 偏移)
Field name 字段名 | Offset 偏移 | Size 大小 | Description 描述 |
---|---|---|---|
BS_DrvNum | 36 | 1 | Drive number used by disk BIOS of IBM PC. This field is used in MS-DOS bootstrap, 0x00 for floppy disk and 0x80 for fixed disk. Actually it depends on the OS. IBM PC 的磁盘 BIOS 使用的驱动器号。 此字段用于 MS-DOS 引导程序,0x00 表示软盘,0x80 表示固定磁盘。 实际上它取决于操作系统。 |
BS_Reserved1 | 37 | 1 | Reserved (used by Windows NT). It should be set 0 when create the volume. 保留(由 Windows NT 使用)。 创建卷时应将其设置为 0。 |
BS_BootSig | 38 | 1 | Extended boot signature (0x29). This is a signature byte indicates that the following three fields are present. 扩展引导签名(0x29)。 这是一个签名字节,表示存在以下三个字段。 |
BS_VolID | 39 | 4 | Volume serial number used with BS_VolLab to track a volume on the removable storage. It enables to detect a wrong media change by FAT driver. This value is typically generated with current time and date on formatting. 与 BS_VolLab 一起使用的卷序列号,用于跟踪可移动存储上的卷。 它可以通过 FAT 驱动程序检测错误的介质更改。 通常使用格式化时的当前时间和日期生成此值。 |
BS_VolLab | 43 | 11 | This field is the 11-byte volume label and it matches volume label recorded in the root directory. FAT driver should update this field when the volume label in the root directory is changed. MS-DOS does it but Windows does not do it. When volume label is not present, "NO NAME " should be set in this field. 此字段是 11 字节的卷标,它与根目录中记录的卷标签匹配。 当根目录中的卷标更改时,FAT 驱动程序应更新此字段。 MS-DOS 做到了这点,但 Windows 没有这样做。 如果不存在卷标,则应在此字段中设置 “NO NAME”。 |
BS_FilSysType | 54 | 8 | "FAT12 ", "FAT16 " or "FAT ". Many people think that this string has any effect in determination of the FAT type but it is clearly a misrecognization. From the name of this field, you will find that this is not a part of BPB. Since this string is often incorrect or not set, Microsoft’s FAT driver does not use this field to determine the FAT type. However, some old FAT drivers use this string to determine the FAT type, so that it should be set based on the FAT type of the volume to avoid compatibility problems. 取值"FAT12 ", "FAT16 " or "FAT "之一。很多人认为这个字符串对 FAT 类型的确定有影响,但显然是个错误的认识。 从该字段的名称,您会发现这不是 BPB 的一部分。 由于此字符串通常不正确或未设置,因此 Microsoft 的 FAT 驱动程序不使用此字段来确定 FAT 类型。 但是,一些旧的 FAT 驱动程序使用此字符串来确定 FAT 类型,因此应根据卷的 FAT 类型进行设置,以避免兼容性问题。 |
BS_BootCode | 62 | 448 | Bootstrap program. It is platform dependent and filled with zero when not used. Bootstrap 程序。 它取决于平台,在不使用时填充为零。 |
BS_BootSign | 510 | 2 | 0xAA55. A boot signature indicating that this is a valid boot sector. 取值 0xAA55。一个引导签名,表明这是一个有效的引导扇区。 |
512 | When the sector size is larger than 512 bytes, rest field in the sector should be filled with zero. 当扇区大小大于 512 字节时,扇区中的剩余部分应填充为零。 |
Fields for FAT32 volumes (offset from 36) FAT32 卷字段(从 36 偏移)
Field name 字段名 | Offset 偏移 | Size 大小 | Description 描述 |
---|---|---|---|
BPB_FATSz32 | 36 | 4 | Size of a FAT in unit of sector. The size of the FAT area is BPB_FATSz32 * BPB_NumFATs sector. This is an only field needs to be referred prior to determine the FAT type while this field exists in only FAT32 volume. But this is not a problem because BPB_FATSz16 is always invalid in FAT32 volume. 以扇区为单位的 FAT 大小(注:即 FAT 区域的扇区数量。与 BPB_FATSz16 含义相同 )。 FAT 区域的大小是 BPB_FATSz32 * BPB_NumFATs 个扇区。 这是在确定 FAT 类型之前需要引用的唯一字段,而该字段仅存在于 FAT32 卷中。 但这不是问题,因为 BPB_FATSz16 在 FAT32 卷中始终无效。 |
BPB_ExtFlags | 40 | 2 | Bit3-0: Active FAT starting from 0. Valid when bit7 is 1. Bit6-4: Reserved (0). Bit7: 0 means that each FAT are active and mirrored. 1 means that only one FAT indicated by bit3-0 is active. Bit15-8-4: Reserved (0). |
BPB_FSVer | 42 | 2 | FAT32 version. Upper byte is major version number and lower byte is minor version number. This document describes FAT32 version 0.0. This field is for futuer extension of FAT32 volume to manage the filesystem verison. However, FAT32 volume will not be updated any longer. FAT32 版本。 高位字节是主要版本号,低位字节是次要版本号。 本文档描述了 FAT32 版本 0.0。 此字段用于将来扩展 FAT32 卷以管理文件系统版本。 但是,FAT32 卷不会再更新。 |
BPB_RootClus | 44 | 4 | First cluster number of the root directory. It is usually set to 2, the first cluster of the volume, but it does not need to always be 2. 根目录的第一个簇的编号。 它通常设置为 2,即卷的第一个簇,但它不必始终为 2。 |
BPB_FSInfo | 48 | 2 | Sector of FSInfo structure in offset from top of the FAT32 volume. It is usually set to 1, next to the boot sector. FSInfo 结构的扇区相对于 FAT32 卷的顶部的偏移。 它通常设置为 1,紧挨着引导扇区。 |
BPB_BkBootSec | 50 | 2 | Sector of backup boot sector in offset from top of the FAT32 volume. It is usually set to 6, next to the boot sector but 6 and any other value is not recommended. 备份引导扇区相对于 FAT32 卷顶部的偏移扇区。它通常设置为 6,紧挨着引导扇区。6 以外的其他值不推荐使用。 |
BPB_Reserved | 52 | 12 | Reserved (0). 保留,全 0 |
BS_DrvNum | 64 | 1 | Same as the description of FAT12/16 field. 与 FAT12/16 中该字段含义相同。 |
BS_Reserved1 | 65 | 1 | Same as the description of FAT12/16 field. 与 FAT12/16 中该字段含义相同。 |
BS_BootSig | 66 | 1 | Same as the description of FAT12/16 field. 与 FAT12/16 中该字段含义相同。 |
BS_VolID | 67 | 4 | Same as the description of FAT12/16 field. 与 FAT12/16 中该字段含义相同。 |
BS_VolLab | 71 | 11 | Same as the description of FAT12/16 field. 与 FAT12/16 中该字段含义相同。 |
BS_FilSysType | 82 | 8 | Always "FAT32 " and has not any effect in determination of FAT type. 取值总是 "FAT32 " 并且与确定 FAT 类型没有任何关系。 |
BS_BootCode32 | 90 | 420 | Bootstrap program. It is platform dependent and filled with zero when not used. Bootstrap 程序。它取决于平台,在不使用时填充为零。 |
BS_BootSign | 510 | 2 | 0xAA55. A boot signature indicating that this is a valid boot sector.取值总是 0xAA55。一个引导签名,表明这是一个有效的引导扇区。 |
512 | When the sector size is larger than 512 bytes, rest part in the sector should be filled with zero. 当扇区大小大于 512 字节时,扇区中的剩余部分应填零。 |
There is another important thing about boot sector. The boot sector needs to be valid only if the boot signature (BS_Sign) contains 0xAA55. If not, the boot sector is invalid. Many FAT documents describe about this field, “Boot signature is put at the end of the boot sector”. This is correct only if the sector size is 512, but it is incorrect in other case. The boot signature must always be put at offset 510 (also it is not bad for both offset 510 and the end of the sector contain this signature). Microsoft’s disk formatter fills the rest part of boot sector with zeros if the sector size is larger than 512.
关于引导扇区还有另一个重要的事情。 仅当引导签名(BS_Sign)包含 0xAA55 时,引导扇区才是有效。 如果不是,则引导扇区无效。 许多 FAT 文档对这个字段有这么一个描述:“引导签名被放在引导扇区的末尾”。 仅当扇区大小为 512 时这个描述才是正确的,在其他情况下则这个描述是不正确的。 引导签名必须始终放在偏移 510 处(对于偏移 510 和扇区的末尾都包含该签名也是不错的)。 如果扇区大小大于 512,则 Microsoft 的磁盘格式化程序用零填充引导扇区的其余部分。
Size of the volume, the value of BPB_TotSec??, might be smaller than the container (storage or partition) where the volume is contained in. It is not a problem at all. The FAT volume sometimes gets this state due to alignment or resize of volume. Such an alignment hole wastes disk space, but it does not mean insanity of the FAT volume itself.
卷的大小(BPB_TotSec?? 的值)可能小于包含卷的容器(存储或分区)。这根本不是问题。 由于卷的对齐或调整大小,FAT 卷有时会出现这种情况。 这样的对齐浪费了磁盘空间,但并不意味着 FAT 卷本身的错乱。
However, if BPB_TotSec?? is larger than the volume’s container, it can be said that the FAT volume is serious state, corrupted volume or incorrectly created volume. Any operation to such volume can result a catastrophic data loss, so that the FAT driver should reject the volume if it detected such condition.
但是,如果 BPB_TotSec?? 大于卷的容器大小,可以说 FAT 卷是严重状态,卷损坏或卷创建错误。 对此类卷的任何操作都可能导致灾难性数据丢失,因此如果 FAT 驱动程序检测到此类情况,则应拒绝该卷。
Calculating Parameters 计算参数
The offset and size of each area are calculated from the parameters in BPB as shown below.
每个区域的偏移量和大小由 BPB 中的参数计算,如下所示。
Since the FAT area is next to the reserved area, its offset and size are:
由于 FAT 区域 位于保留区域的旁边,因此其偏移量和大小为:
FatStartSector = BPB_ResvdSecCnt;
FatSectors = BPB_FATSz * BPB_NumFATs;
The offset and size of the root directory are:
根目录区域 的偏移量和大小为:
RootDirStartSector = FatStartSector + FatSectors;
RootDirSectors = (32 * BPB_RootEntCnt + BPB_BytsPerSec - 1)/BPB_BytsPerSec;
The 32 in the equation is the size of a directory entry. A remainder at the divsion is rounded up, but such configuration that gives remainder is not recommended. On the FAT32 volumes, BPB_RootEntCnt is always 0 and the root directory area is not exist. The data area becomes the rest of these areas and it is obtained as follows.
等式中的 32 是目录项的大小。除法中的余数是四舍五入的,但是不建议使用这种给出余数的配置。在 FAT32 卷上,BPB_RootEntCnt 总是 0,根目录区域不存在。数据区域变成这些区域的其余部分,得到如下结果。
DataStartSector = RootDirStartSector + RootDirSectors;
DataSectors = BPB_TotSec - DataStartSector;
If the volume does not start from the top of the storage, for example when the storage is partitioned, these start sector numbers are not equal to the physical sector number.
如果卷不是从存储的顶部开始,例如,当存储被分区时,这些起始扇区号不等于物理扇区号。
FAT and Cluster FAT 区域和数据区的簇
The another important area is FAT. What this structure does is define a linked list of the extents (cluster chain) of a file. Note that both directroy and file is contained in the file and nothing different on the FAT. The directory is really a file with a special attribute that indicates its content is a directory table.
另一个重要的区域是 FAT 区域。这个结构的作用是定义一个文件的区段(簇链)的链表。注意,directroy 和 file 都包含在文件中,FAT 上没有什么不同。目录实际上是一个具有特殊属性的文件,该属性指示其内容是一个目录表。关于目录在下文的 FAT 目录 章节还会有详细介绍!
FAT 区域 通常至少有 2 个完全一样的 FAT 表,多余的 FAT 表作为备份使用。FAT 表用于指示一个文件的各个部分存放在何处。其中,一个 FAT 表条目对应数据区域的一个簇。如下图所示:
FAT 表条目大小根据 FAT 类型不同而变,FAT 表条目中,填写一下几种值
- 链中下一个簇的地址
- 一个特殊的簇链结束符(EOC,End Of Cluster-chain,或称End Of Chain)符号指示链的结束
- 一个特殊的符号标示坏簇
- 一个特殊的符号标示保留簇
- 0来表示空闲簇
关于这部分的详细信息(FAT 条目的大小,FAT 条目的取值等),后文还会有更信息的介绍。
The data area is divided into blocks of a certain number of sectors (BPB_SecPerClus) called cluster and the data area is managed in this unit. Each item of FAT is associated with each cluster in the data area and the FAT value indicates the state of the corresponding cluster. However, the top two FAT items, FAT[0] and FAT[1], are reserved and not associated with any cluster. The third FAT item, FAT[2], is the item associated with the first cluster of data area and the valid cluster number starts at 2. As for the data recorded on the FAT, see Association of File and Cluster.
数据区域被划分为包含一定数量扇区(BPB_SecPerClus)的被称为簇的块,并且在该单元中管理数据区域。 如下所示的数据区域结构
上图中省略的头部结构可以参看本章节开始的第一幅图。每个部分都有大小限制,上图中的字母仅仅是为了区分大小关系,具体各部分的大小限制请看如下文章的介绍。
FAT 表中的每个 FAT 条目与数据区中的每个簇相关联,FAT 值指示相应簇的状态。 但是,前两个 FAT 项目 FAT[0] 和 FAT[1] 是保留的,不与任何簇关联。 第三个 FAT 项目 FAT[2] 是与第一个数据区域簇相关联的项,有效簇编号从 2 开始。 至于 FAT 上记录的数据,请参阅文件和簇关联。
FAT is usually duplicated for the redundancy because a damage of any FAT sector results a serious data loss. Number of FAT copyies indicated by BPB_NumFATs and the size of FAT area becomes BPB_FATSz * BPB_NumFATs. FAT driver typically refers only first FAT copy and any update to the FAT item is refrected every FAT copy.
FAT 通常会有个冗余备份区,因为任何 FAT 扇区的损坏都会导致严重的数据丢失。 BPB_NumFAT 指示的 FAT 副本数量并且 FAT 区域的大小变为 BPB_FATSz * BPB_NumFATs。 FAT 驱动程序通常仅引用第一个 FAT 副本,并且任何更新对于 FAT 条目的更新,都会重新更新到每个 FAT 副本。如下图所示:
Determination of FAT sub-type FAT 子类型的确定
There are three FAT types, FAT12, FAT16 and FAT32, need to be determined on mount a FAT volume. However there is considerable confusion over exactly how this works and it leads various degree of errors. It is really quite simple how this works.
有三种 FAT 类型,FAT12,FAT16 和 FAT32,需要在安装 FAT 卷时确定。 然而,对于它是如何工作的并且它导致各种程度的错误存在相当大的混淆。 它的工作原理非常简单。
The FAT type is determined by the count of clusters on the volume and NOTHING ELSE.
FAT 类型由卷上的簇数和 NOTHING ELSE 确定。
The count of clusters is that can exist in the data area, the quotient of size of the data area divided by cluster size. Remainder is ignored if it exist in the result.
簇的数量可以由数据区域计算得出,值为数据区域的大小除以簇大小的商。 如果结果中存在余数,则忽略余数。
CountofClusters = DataSectors/BPB_SecPerClus;
Once you know the count of clusters you can determine the FAT type. This is done as follows:
一旦知道了簇的数量,就可以确定 FAT 类型。 这样做如下:
- A volume with count of clusters <=4085 is FAT12. 具有簇数 <= 4085 的卷是 FAT12。
- A volume with count of clusters >=4086 and <=65525 is FAT16. 具有簇数 >= 4086 且 <= 4085 的卷是 FAT16。
- A volume with count of clusters >=65526 is FAT32. 具有簇数 >= 65526 的卷是 FAT32。
This is the only way to determine the FAT type. FAT12 volumes never have clusters more than 4085 and FAT16 volumes never have clusters less than 4086 or more than 65525. If you tried to create an illegal FAT volume out of this rule, the properly designed FAT driver will recognize it as a different FAT type and will not able to access such volume. Maximum cluster count for FAT32 volume is not defined and the practical limit is 268435445.
这是确定 FAT 类型的唯一方法。 FAT12 卷永远不会有超过 4085 的簇,FAT16 卷永远不会有小于 4086 或超过 65525 的簇。如果您尝试使用此规则创建非法 FAT 卷,正确设计的 FAT 驱动程序会将其识别为不同的 FAT 类型和将无法访问此类卷。 FAT32 卷的最大簇数并没有定义,实际限制为 268435445。
However, these boundaries are really not strictly settled. From the maximum possible values of the cluster number, it will gets as described above, but there are many variants (1, 2, 16 or more) over the existing documentations and software implementations. For example about maximum count of clusters of FAT12, the FAT specs says it is 4084, while MSDN page says it is 4085 and Windows works with 4085 (FAT driver) or 4086 (chkdsk). Even the authorized documentation and the standad system differ as to what the correct value is, so that it is recommended to avoid count of clusters close to the boundaries when create a FAT volume. The FAT specs says count of clusters should be at least 16 clusters off from the boundaries.
但是,这些界限实际上并没有严格解决。 符合如上所述的簇号的最大可能值在现有文档和软件实现上存在许多变体(1, 2, 16 或更多)。 例如,关于 FAT12 簇的最大数量,FAT 规范表示它是 4084,而 MSDN 页面表示它是 4085,Windows 使用 4085(FAT 驱动程序)或 4086(chkdsk)。 即使授权文档和标准系统采用的正确值也不同,因此建议在创建 FAT 卷时避免簇数量接近限制边界。 FAT 规范说簇的数量应该至少距边界 16 个簇。
Also, some FAT driver written in out of this rule seem to determine the FAT type without the count of clusters but the string of BS_FilSysType. In order to support such the wrong FAT drivers, it is recommended to initialize BS_FilSysType with a proper string based on actual FAT type when create a FAT volume.
此外,根据这条规则编写的一些 FAT 驱动程序似乎在不计算簇数量的情况下确定 FAT 类型,而是使用 BS_FilSysType 字符串。 为了支持这种错误的 FAT 驱动程序,建议在创建 FAT 卷时使用基于实际 FAT 类型的正确字符串初始化 BS_FilSysType。
You will understand what the count of clusters determins the FAT type means which FAT type can be legal depends on the volume size. For example under the condition of cluster size of from 512 to 32768 bytes, it can be saied as follows:
您将了解,簇的数量确定 FAT 类型意味着哪种 FAT 类型合法取决于卷大小。 例如,在簇大小为 512 到 32768 字节的情况下,可以如下所示:
FAT type FAT 类型 | Volume size 卷大小 |
---|---|
FAT12 | -128 MB |
FAT16 | 2 MB - 2 GB |
FAT32 | 32 MB - 2 TB |
Accessing FAT Entries 访问 FAT 条目
An important thing related to FAT is how to access the FAT entries. First of all, you need to know where the FAT entry is located in the FAT. At the FAT16/32, it is quite simple. FAT is a simple generic integer array. The difference from the on-memory array is that the FAT is not on the continuous memory but divided in multiple blocks and stored on the contiguous disk sectors origin from the first sector of the FAT. The location of the FAT entry FAT[N], the sector number and byte offset in the sector, can be got by following calculation.
与 FAT 区域相关的一个重要事项是如何访问 FAT 条目。 首先,您需要知道 FAT 条目在 FAT 区域中的位置。 在 FAT16/32 中,它非常简单。 FAT 是一个简单的通用整数数组。 与内存中数组的不同之处在于 FAT 不在连续存储器上,而是分成多个块并存储在来自 FAT 的第一扇区的连续磁盘扇区上。 FAT 条目 FAT[N] 的位置,扇区中的扇区号和字节偏移量,可以通过以下计算得到。
FAT16 entry location:
ThisFATSecNum = BPB_ResvdSecCnt + (N * 2/BPB_BytsPerSec);
ThisFATEntOffset = (N * 2) % BPB_BytsPerSec;
FAT32 entry location:
ThisFATSecNum = BPB_ResvdSecCnt + (N * 4/BPB_BytsPerSec);
ThisFATEntOffset = (N * 4) % BPB_BytsPerSec;
The 2 (FAT16) or 4 (FAT32) byte word from the location is the FAT entry to access. The byte order is little endian. The FAT entries never across sector boundaries at FAT16/32.
上式中的 2(FAT16)或 4(FAT32)是 FAT 条目的大小。 字节顺序是小端。 FAT 条目从不跨越 FAT16/32 的扇区边界。
There is another important thing about FAT32. The FAT entry of FAT32 volume occupies 32 bits, but its upper 4 bits are reserved, only lower 28 bits are valid. The reserved bits are initialized by zero when createing the FAT32 volume, and it should not be changed on the regular use. Therefore, when load the value from the FAT entry of the FAT32 volume, upper 4 bits needs to be and-masked with 0x0FFFFFFF. Also, when store a value into the FAT entry, the upper 4 bits in the FAT entry need to be preserved.
关于 FAT32 还有另一个重要的事情。 FAT32 卷的 FAT 条目占用 32 位,但其高 4 位保留,只有低 28 位有效。 在创建 FAT32 卷时,保留位由零初始化,并且在常规使用时不应更改。 因此,当从 FAT32 卷的 FAT 条目加载值时,高 4 位需要用0x0FFFFFFF 进行掩码。 此外,当将值存储到 FAT 条目中时,需要保留 FAT 条目中的高 4 位。
Load a value of FAT32 entry:
ReadSector(SecBuff, ThisFATSecNum);
ThisEntryVal = *(uint32*)&SecBuff[ThisFATEntOffset] & 0x0FFFFFFF;
Store a value of FAT32 entry:
ReadSector(SecBuff, ThisFATSecNum);
tmp = *(uint32*)&SecBuff[ThisFATEntOffset];
tmp = (tmp & 0xF0000000) | (NewEntryVal & 0x0FFFFFFF);
*(uint32*)&SecBuff[ThisFATEntOffset] = tmp;
WriteSector(SecBuff, ThisFATSecNum);
It is a little difficult at the FAT12 volume. The FAT12 entry is in bit field and it needs a complicated operation.
对于 FAT12 卷,则有点困难。 FAT12 条目位于字段中,需要复杂的操作。
FAT12 entry location:
ThisFATSecNum = BPB_ResvdSecCnt + ((N + (N/2))/BPB_BytsPerSec);
ThisFATEntOffset = (N + (N/2)) % BPB_BytsPerSec;
Load a value of FAT12 entry:
ReadSector(SecBuff, ThisFATSecNum);
if (N & 1) { /* Odd entry */
ThisEntryVal = (SecBuff[ThisFATEntOffset] >> 4)
| ((uint16)SecBuff[ThisFATEntOffset + 1] << 4);
} else { /* Even entry */
ThisEntryVal = SecBuff[ThisFATEntOffset]
| ((uint16)(SecBuff[ThisFATEntOffset + 1] & 0x0F) << 8);
}
Store a value of FAT12 entry:
ReadSector(SecBuff, ThisFATSecNum);
if (N & 1) { /* Odd entry */
SecBuff[ThisFATEntOffset] = (SecBuff[ThisFATEntOffset] & 0x0F)
| (NewEntryVal << 4);
SecBuff[ThisFATEntOffset + 1] = NewEntryVal >> 4;
} else { /* Even entry */
SecBuff[ThisFATEntOffset] = NewEntryVal;
SecBuff[ThisFATEntOffset + 1] = (SecBuff[ThisFATEntOffset + 1] & 0xF0)
| ((NewEntryVal >> 8) & 0x0F);
}
WriteSector(SecBuff, ThisFATSecNum);
Unfortunately, this code does not work properly because the bit field spans over a sector boundary when ThisFATEntOffset points the last byte of the sector and it needs to be handled properly.
不幸的是,这段代码不能正常工作,因为当 ThisFATEntOffset 指向扇区的最后一个字节时,位字段跨越扇区边界,需要正确处理。
Following image shows the FAT usage of each FAT type
下图显示了每种 FAT 类型的 FAT 使用情况
Association of File and Cluster 文件和簇的关联
Files on the FAT volume are managed by directory, the array of 32-byte directory entry structures. Details of the directory entry is described below. The directory entry has the file name, file size, timestamp and the first cluster number of the file data. The cluster number is the entry point to follow the cluster chain of the file data. If the file size is zero, a zero is set to the first cluster number and no data cluster is allocated to the file.
FAT 卷上的文件由目录管理,目录是 32 字节目录条目结构的数组。 目录条目的细节描述如下。 目录条目具有文件名,文件大小,时间戳和文件数据的第一个簇号。 簇号是跟随文件数据的簇链的入口点。 如果文件大小为零,则将零设置为第一个簇号,并且不为该文件分配数据簇。
As described above, cluster number 0 and 1 are reserved and valid cluster number starts from 2. The cluster number 2 corresponds to the first cluster of the data area. Therefore, valid cluster number is from 2 to N + 1 and count of FAT entries is N + 2 in the volume with N clusters. The location of a data cluster N is calculated as follows:
如上所述,簇号 0 和 1 保留,并且有效簇号从 2 开始。簇号 2 对应于数据区域的第一簇。 因此,有效簇号从 2 到 N + 1,并且在具有 N 个簇的卷中 FAT 条目的数量是 N + 2。 数据簇 N 的位置计算如下:
FirstSectorofCluster = DataStartSector + (N - 2) * BPB_SecPerClus;
If the file size is larger than the sector size, file data is spanning over multiple sectors in the cluster. If the file size is larger than the cluster size, file data is spanning over multiple clusters in the cluster chain. The value of the FAT entry indicates following cluster number if exist, so that the any byte offset in the file can be reached by following the cluster chain. The cluster chain cannot be followed backward. The FAT entry with last link of cluster chain has a special value (end of chain, EOC, mark), which is never matches any valid cluster number. The EOC mark for each FAT type is as follows:
如果文件大小大于扇区大小,则文件数据跨越簇中的多个扇区。 如果文件大小大于簇大小,则文件数据跨越簇链中的多个簇。 FAT 条目的值表示如果存在以下簇号,则可以通过跟随簇链到达文件中的任何字节偏移量。 簇链不能向后追踪。 具有簇链的最后一个链接的 FAT 条目具有特殊值(链的末尾,EOC,标记),它永远不会匹配任何有效的簇号。 每种 FAT 类型的 EOC 标记如下:
- FAT12: 0xFF8 - 0xFFF (typically 0xFFF)
- FAT16: 0xFFF8 - 0xFFFF (typically 0xFFFF)
- FAT32: 0x0FFFFFF8 - 0x0FFFFFFF (typically 0x0FFFFFFF)
There is also a special value, bad cluster mark. The bad cluster mark indicates that there is a defective sector in the cluster and it cannot be used. The bad cluster found on the format, surface inspection or disk repair is recorded in the FAT as bad cluster mark. The value of bad cluster mark is 0xFF7 for FAT12, 0xFFF7 for FAT16 and 0x0FFFFFF7 for FAT32.
还有一个特殊值,坏簇标记。 坏簇标记表示簇中存在缺陷扇区,无法使用。 在格式化,表面检查或磁盘修复中发现的坏簇在 FAT 中记录为坏簇标记。 FAT12 的坏簇标记值为 0xFF7,FAT16 为 0xFFF7,FAT32 为 0x0FFFFFF7。
The value of bad cluster mark never be equal to any valid cluster number on the FAT12/16 volume. However, it can be equal to any allocatable cluster number because the maximum count of clusters is not defined in FAT32. Such FAT32 volumes can make disk utilities confuse, so that you should avoid creating such FAT32 volume. Therefore, the upper limit of cluster count of FAT32 volume is practicaly 268435445 (about 256 M clusters).
坏簇标记的值永远不会等于 FAT12/16 卷上的任何有效簇号。 但是在 FAT32 中,它可以等于任何可分配的簇号,因为在 FAT32 中未定义簇的最大数量。 这样的 FAT32 卷可能会使磁盘实用程序混淆,因此您应该避免创建此类 FAT32 卷。 因此,FAT32 卷的簇数的上限实际为 268435445(约256M簇)。
Some system has a limitation on the maximum cluster count due to implementation reasons. For example, Windows9X/Me supports the FAT size 16 MB maximum and it limits number of clusters about 4 M clusters maximum.
由于实现原因,某些系统对最大簇数有限制。 例如,Windows9X/Me 支持最大 16 MB 的 FAT 大小,并且它最多限制大约 4M 个簇的簇数量。
The initial value of each allocatable FAT entry, FAT[2] and followings, is zero, which indicats the cluster is not in use and free for a new allocation. If the value is not zero, it means the cluster is in use or bad. Free cluster count is not recoreded anywhere in the FAT12/16 volume and full FAT scan is needed to get this information. FAT32 supports FSInfo to store the free cluster count to avoid full FAT scan because of its very large FAT structure.
每个可分配的 FAT 条目(FAT[2] 及其后的)初始值为零,表示簇未使用且可用于新分配。 如果该值不为零,则表示簇正在使用或不良。 FAT12/16 卷中的任何位置都不会记录空闲簇计数,并且需要完整的 FAT 扫描才能获取此信息。 FAT32 支持 FSInfo 存储空闲簇计数,以避免完全 FAT 扫描,因为它具有非常大的 FAT 结构。
The top two FAT entry, FAT[0] and FAT[1], are reserved and not associated with any cluster. These FAT entries are initialized on creating the volume as follows:
前两个 FAT 条目 FAT[0] 和 FAT[1] 是保留的,不与任何簇相关联。 这些 FAT 条目在创建卷时初始化,如下所示:
- FAT12: FAT[0] = 0xF??; FAT[1] = 0xFFF;
- FAT16: FAT[0] = 0xFF??; FAT[1] = 0xFFFF;
- FAT32: FAT[0] = 0xFFFFFF??; FAT[1] = 0xFFFFFFFF;
?? in the value of FAT[0] is the same value of BPB_Media but the entry has not any function. Some bits in the FAT[1] records error history.
FAT[0] 的值中的 ?? 与 BPB_Media 的值相同,但该条目没有任何功能。 FAT[1] 中的某些位记录错误历史记录。
- Volume dirty flag: (FAT16: bit15、FAT32: bit31): Cleared on boot, restored on clean shutdown. Clearing before boot indicates a possibility of insanity in the volume. 在启动时清除,在完全关闭时恢复。在启动前清除指示卷中有精神错乱的可能性。
- Hard error flag: (FAT16: bit14、FAT32: bit30): Cleared on unrecoverable read/write error, set after surface inspection. 清除不可恢复的读/写错误,在表面检查后设置。
These flags indicates possibility of an error on the volume. Some OSs supporing this feature check these flags on boot and launch disk inspection tool automatically. Windows 9X family uses these flags. Windows NT family does not use these flags but alternatives in the BPB.
这些标志表示卷上可能出错。 某些支持此功能的操作系统会在启动时检查这些标志并自动启动磁盘检查工具。 Windows 9X 系列使用这些标志。 Windows NT 系列不使用这些标志,而是使用 BPB 中的替代标志。
There are two more important things about the FAT area. One is that the last sector of a FAT may not be fully used. In most case, FAT ends at the middle of the sector. FAT driver should not have any assumption about unused part. It should be initialized by zero on formatting the volume and should not change afterwards. The other is that the BPB_FATSz16/32 can indicates a value lager than the volume requires. In other wards, unused sectors can follow the used FAT sectors. It may a result of data area alignment or something. Also these sector are initialized to zero on formatting.
关于 FAT 区域有两个更重要的事情。 一个是 FAT 的最后一个扇区可能没有被完全使用。 在大多数情况下,FAT 结束于扇区的中间。 FAT 驱动程序不应该对未使用的部分有任何假设。 它应该在格式化卷时初始化为零,之后不应更改。 另一个是 BPB_FATSz16/32 可以指示比卷要求的更大的值。 换句话说,未使用的扇区可以跟随使用的 FAT 扇区。 它可能是数据区域对齐的结果。 这些扇区在格式化时也被初始化为零。
Following table shows the range of FAT values and meaning for each FAT type.
下表显示了每种 FAT 类型的 FAT 值范围和含义。
FAT12 | FAT16 | FAT32 | Meaninig |
---|---|---|---|
0x000 | 0x0000 | 0x00000000 | Free 空闲簇 |
0x001 | 0x0001 | 0x00000001 | Reserved 保留簇 |
0x002 - 0xFF6 | 0x0002 - 0xFFF6 | 0x00000002 - 0x0FFFFFF6 | In use (value is link to next) 被占用的簇;指向下一个簇 |
0xFF7 | 0xFFF7 | 0x0FFFFFF7 | Bad cluster 坏簇 |
0xFF8 - 0xFFF | 0xFFF8 - 0xFFFF | 0x0FFFFFF8 - 0x0FFFFFFF | In use (end of chain) 文件最后一个簇 |
下图显示了 从 FAT 区中的 FAT 条目 到 数据区簇的关系(简化形式)
FAT 区域示例
上面详细介绍了 FAT 区域的内容。每个版本的 FAT 文件系统使用不同大小的 FAT 条目。这个大小已经由名字表示出来,例如 FAT16 文件系统的每个条目使用 16位表示,FAT32 文件系统使用 32 位表示。下面我们以图示的形式来看一下。
FAT12
FAT12 文件系统每个 FAT 条目使用 12 个比特位,因此两个条目跨越 3 个字节。 它始终是小端。如果这三个字节被视为一个小端 24 位数,则 12 个最低有效位表示第一个条目(fe簇0),12 个最高有效位表示第二个(fe簇1) 。 换句话说,虽然行中第一个簇的低 8 位存储在第一个字节中,但前 4 位存储在第二个字节的低半字节中,而后续簇中的低 4 位存储在第二个字节中。 存储在第二个字节的高半字节中,在第三个字节中存储在高位的 8 位中。
- 蓝色:非碎片文件的第二个链:簇 2 -> 簇 3 -> 簇 4 -> 簇 5 -> 簇 6 -> 簇 7 -> 簇 8(结束),共 7 个簇
- 黄色:第三个链,用于碎片化的、可能增长的文件:簇 9 -> 簇 A -> 簇 14 -> 簇 15 -> 簇 16 -> 簇 19 -> 簇 1A(结束),共 7 个簇
- 橙色:第四个链。用于一个非碎片的、可能被截断的文件:簇 B -> 簇 C -> 簇 D -> 簇 E -> 簇 F -> 簇 10 -> 簇 11(结束),共 7 个簇
- 白色:空闲簇未使用
- 浅红色:坏簇
- 浅绿色:第五个链,指示子目录
FAT16
FAT16 文件系统每个 FAT 条目使用 16 位,因此一个条目以小端字节顺序跨越两个字节:
- 蓝色:非碎片文件的第二个链:簇 2 -> 簇 3 -> 簇 4 -> 簇 5 -> 簇 6 -> 簇 7 -> 簇 8(结束),共 7 个簇
- 黄色:第三个链,用于碎片化的、可能增长的文件:簇 9 -> 簇 A -> 簇 14 -> 簇 15 -> 簇 16 -> 簇 19 -> 簇 1A(结束),共 7 个簇
- 橙色:第四个链。用于一个非碎片的、可能被截断的文件:簇 B -> 簇 C -> 簇 D -> 簇 E -> 簇 F -> 簇 10 -> 簇 11(结束),共 7 个簇
- 白色:空闲簇未使用
- 浅红色:坏簇
- 浅绿色:第五个链,指示子目录
FAT32
FAT32文件系统每个FAT条目使用32位,因此一个条目以小端字节顺序跨越四个字节。 每个条目的高四个比特位保留用于其他目的,在格式化期间清除,否则不应更改。 在将条目解释为 28 位簇地址之前,必须将它们屏蔽掉。
- 绿色:根目录的第一个链,由 FAT32 BPB 中的一个条目指向:簇 2(结束),共 1 个簇
- 蓝色:非碎片文件的第二个链:簇 2 -> 簇 3 -> 簇 4 -> 簇 5 -> 簇 6 -> 簇 7 -> 簇 8(结束),共 7 个簇
- 黄色:第三个链,用于碎片化的、可能增长的文件:簇 9 -> 簇 A -> 簇 14 -> 簇 15 -> 簇 16 -> 簇 19 -> 簇 1A(结束),共 7 个簇
- 橙色:第四个链。用于一个非碎片的、可能被截断的文件:簇 B -> 簇 C -> 簇 D -> 簇 E -> 簇 F -> 簇 10 -> 簇 11(结束),共 7 个簇
- 白色:空闲簇未使用
- 浅红色:坏簇
- 浅绿色:第五个链,指示子目录
FSInfo Sector Structure and Backup Boot Sector FSInfo扇区结构和备份引导扇区
The size of FAT is up to 6 KB on FAT12 volume and up to 128 KB on FAT16 volume, but it typically reach several MB on FAT32 volume. For this reason, FAT32 volume supports FSInfo structure in order to avoid to read over an entire FAT to look for free clusters or get count of free clusters. This structure is put in the FSInfo sector indicated by BPB_FSInfo.
在 FAT12 卷上 FAT 区域的大小最多为 6KB,在 FAT16 卷上最大为 128KB,但在 FAT32 卷上它通常达到几 MB。 出于这个原因,FAT32 卷支持 FSInfo 结构,以避免读取整个 FAT 以查找空闲簇或获取空闲簇的数量。 此结构放在 BPB_FSInfo 指示的FSInfo 扇区中。
FAT32 FSInfo sector
Field name 字段名 | Offset 偏移 | Size 大小 | Description 描述 |
---|---|---|---|
FSI_LeadSig | 0 | 4 | 0x41615252. This is a lead signature used to validate that this is in fact an FSInfo sector. 取值 0x41615252。这是用于验证这实际上是 FSInfo 扇区的主要签名。 |
FSI_Reserved1 | 4 | 480 | Reserved. This field should be always initialized to zero. 保留。 该字段应始终初始化为零。 |
FSI_StrucSig | 484 | 4 | 0x61417272. Another signature that is more localized in the sector to the location of the fields that are used.取值 0x41615252。这是用于验证这实际上是 FSInfo 扇区的主要签名。 |
FSI_Free_Count | 488 | 4 | This field indicates the last known free cluster count on the volume. If the value is 0xFFFFFFFF, it is actually unknown. This is not necessarily correct, so that the FAT driver needs to make sure it is valid for the volume.此字段指示卷上最后一次已知的可用簇计数。 如果值为 0xFFFFFFFF,则实际上是未知的。 这不一定正确,因此 FAT 驱动程序需要确保它对卷有效。 |
FSI_Nxt_Free | 492 | 4 | This field gives a hint for the FAT driver, the cluster number at which the driver should start looking for free clusters. Because a FAT32 FAT is large, it can be rather time consuming if there are a lot of allocated clusters at the start of the FAT and the driver starts looking for a free cluster starting at the first cluster. Typically this value is set to the last cluster number that the driver allocated. If the value is 0xFFFFFFFF, there is no hint and the driver should start looking at cluster 2. This may not be correct, so that the FAT driver needs to make sure it is valid for the volume. 该字段为 FAT 驱动程序提供一个提示,FAT 驱动程序应该从此簇号开始寻找空闲簇。因为 FAT32 FAT 很大,如果在 FAT 的开始有很多分配的簇,并且驱动程序从第一个簇开始寻找空闲簇,那么它可能会非常耗时。 通常,此值设置为驱动程序分配的最后一个簇编号。 如果值为 0xFFFFFFFF,则没有提示,驱动程序应该从簇 2 开始查看。这可能不正确,因此 FAT 驱动程序需要确保它对该卷有效。 |
FSI_Reserved2 | 496 | 12 | Reserved. This field should be always initialized to zero. 保留。 该字段应始终初始化为零。 |
FSI_TrailSig | 508 | 4 | 0xAA550000. This trail signature is used to validate that this is in fact an FSInfo sector. 取值 0xAA550000。该跟踪签名用于验证这实际上是一个FSInfo扇区。 |
512 | When the sector size is larger than 512, rest bytes should be initialized to zero.当扇区大小大于512时,剩余字节应初始化为零。 |
Another feature of FAT32 volume is backup boot sector. This is a feature to provide redundancy for the only boot sector existing on the FAT volume. This can increase the possibility of volume recovery if the boot sector is corrupted for any reason. The location of backup boor sector is indicated by BPB_BkBootSec. 6 is strongly recommended for this field because the boot loader and FAT driver are hard coded to try reading the boot sector at sector 6 when it failed to load the main boot sector. The FAT32 boot sector is actually three 512-byte sectors long. There is a copy of all three of these sectors starting at the sector indicated by BPB_BkBootSec. A copy of the FSInfo sector is also there, even though the BPB_FSInfo field in this backup boot sector is set to the same value as the value in sector 0. All three sectors have boot signature, 0xAA55, at the offset 510.
FAT32 卷的另一个特征是备份引导扇区。这是为 FAT 卷上存在的唯一引导扇区提供冗余的功能。如果引导扇区因任何原因损坏,这将增加卷恢复的可能性。备份扇区的位置由 BPB_BkBootSec 指示。强烈建议在此字段中使用 6,因为引导加载程序和 FAT 驱动程序被硬编码,以便在未能加载主引导扇区时尝试读取扇区 6 的引导扇区。FAT32 引导扇区实际上有三个 512 字节长的扇区。所有这三个扇区都有一个副本,从BPB_BkBootSec 指示的扇区开始。即使备份引导扇区中的 BPB_FSInfo 字段被设置为与扇区 0 中的值相同的值,FSInfo扇区的副本也在那里。所有三个扇区都在偏移量 510 处具有引导签名 0xAA55。
FAT Directory FAT 目录(FAT 根目录区域)
FAT 卷上的文件由根目录管理,根目录是 32 字节目录条目结构的数组(根目录表)。 目录条目的细节描述如下。 目录条目具有文件名,文件大小,时间戳和文件数据的第一个簇号。 簇号是跟随文件数据的簇链的入口点。 如果文件大小为零,则将零设置为第一个簇号,并且不为该文件分配数据簇。
对于 FAT12 和 FAT16 ,根目录位于紧跟在最后一个 FAT 之后的固定位置,在扇区中具有固定大小根据 BPB_RootEntCnt 值计算。对于 FAT32,根目录可以是可变大小的簇链,就像任何其他目录一样。FAT32 卷上的根目录的第一个出存储在 BPB_RootClus 中。
This section describes only short file name (SFN), the basic feature of FAT volume. The directory is really a file with a special attribute. It contains table of directory entries that contain meta data of the files on the volume. Size of a directory entry is 32 byte long and it corresponds with a file or diretory on the volume. Maximum size of a directory is 2 MB (65536 entries).
本节仅介绍短文件名(SFN),即 FAT 卷的基本特性。目录实际上是一个具有特殊属性的文件。 它包含目录条目表,其中包含卷上文件的元数据。 目录条目的大小为 32 字节长,它对应于卷上的文件或指令。 目录的最大大小为 2 MB(65536个条目)。
The root directory is only a special directory needs to be always exist and it becomes top node of the hierarchy in the volume. On the FAT12/16 volume, the root directory is not a file but put on the root directory area separated form the data area. The count of root directory entries is determined on the formatting and indicated in BPB_RootEntCnt. On the FAT32 volume, there is no difference between the sub-directories except for it does not have any entry to indicate it and the start cluster number is indicated by BPB_RootClus.
根目录只是一个特殊目录,需要始终存在,并且它成为卷中层次结构的顶级节点。 在 FAT12/16 卷上,根目录不是文件,而是放在与数据区分开的根目录区。 根目录条目的计数是根据格式确定的,并在 BPB_RootEntCnt 中指示。 在 FAT32 卷上,子目录之间没有区别,只是没有任何条目来表示它,并且起始簇号由 BPB_RootClus 指示。
Another difference from the sub-directory is that it does not contain dot entries (".", “…”) what always exist in the sub-directory and it can contain a volume label (an entry with ATTR_VOLUME_ID attribute). Following table shows directory entry structure
与子目录的另一个不同之处在于它不包含在子目录中始终存在的点条目(“ . ”,“ … ”),它可以包含卷标(具有ATTR_VOLUME_ID 属性的条目)。 下表显示了目录条目结构
Directory entry structure
Field name 字段名 | Offset 偏移 | Size 大小 | Description 描述 |
---|---|---|---|
DIR_Name | 0 | 11 | Short file name (SFN) of the object. 对象的短文件名(SFN)。 |
DIR_Attr | 11 | 1 | File attribute in combination of following flags. Upper 2 bits are reserved and must be zero.文件属性,由以下标志组合而成。 高 2 位保留,必须为零。 0x01: ATTR_READ_ONLY (Read-only) 0x02: ATTR_HIDDEN (Hidden) 0x04: ATTR_SYSTEM (System) 0x08: ATTR_VOLUME_ID (Volume label) 0x10: ATTR_DIRECTORY (Directory) 0x20: ATTR_ARCHIVE (Archive) 0x0F: ATTR_LONG_FILE_NAME (LFN entry) |
DIR_NTRes | 12 | 1 | Optional flags that indicates case information of the SFN. 可选标志,指示SFN的案例信息。 0x08: All alphabetical characters in the body are lower capital.正文中所有字母都是小写字母。 0x10: All alphabetical characters in the extensiton are lower capital. 扩展中的所有字母字符都是小写字母。 |
DIR_CrtTimeTenth | 13 | 1 | Optional sub-second information corresponds to DIR_CrtTime. The time resolution of DIR_CrtTime is 2 seconds, so that this field gives a count of sub-second and its valid value range is from 0 to 199 in unit of 10 miliseconds. If not supported, set zero and do not change afterwards. 可选的亚秒信息对应于 DIR_CrtTime。 DIR_CrtTime 的时间分辨率为2秒,因此该字段给出亚秒计数,其有效值范围为 0 到 199,单位为 10 毫秒。 如果不支持,请设置为零,之后不要更改。 |
DIR_CrtTime | 14 | 2 | Optional file creation time. If not supported, set zero and do not change afterwards. 可选的文件创建时间。 如果不支持,请设置为零,之后不要更改。 |
DIR_CrtDate | 16 | 2 | Optional file creation date. If not supported, set zero and do not change afterwards. 可选的文件创建日期。 如果不支持,请设置为零,之后不要更改。 |
DIR_LstAccDate | 18 | 2 | Optional last accesse date. There is no time information about last accesse time, so that the resolution of last accesse time is 1 day. If not supported, set zero and do not change afterwards. 可选的上次访问日期。 没有关于上次访问时间的时间信息,因此最后访问时间的分辨率为1天。 如果不支持,请设置为零,之后不要更改。 |
DIR_FstClusHI | 20 | 2 | Upeer part of cluster number. Always zero on the FAT12/16 volume. 簇号的上半部分。 FAT12/16 卷始终为零。 |
DIR_WrtTime | 22 | 2 | Last time when any change is made to the file (typically on closeing). 对文件进行任何更改时的上次时间(通常在关闭时)。 |
DIR_WrtDate | 24 | 2 | Last data when any change is made to the file (typically on closeing).对文件进行任何更改时的最后数据(通常在关闭时)。 |
DIR_FstClusLO | 26 | 2 | Lower part of cluster number. Always zero if the file size is zero. 簇号的下半部分。 如果文件大小为零,则始终为零。其表示文件或者目录的第一个簇号。如果是 FAT32 则,需要还需要 + DIR_FstClusHI。 |
DIR_FileSize | 28 | 4 | Size of the file in unit of byte. Not used when it is a directroy and the value must be always zero.文件大小,以字节为单位。 当它是目录时不使用,值必须始终为零。 |
The first byte of DIR_Name field, DIR_Name[0], is an impotant data to indicates state of the directory entry. When the value is 0xE5, it indicates that the entry is not used (free for new allocation). When the value is 0x00, it indicates that the entry is not used (same as 0xE5) and in addition, there is no allocated entry after this one (all of the DIR_Name[0] in all of the entries after this one are also set to 0). Any other value in the DIR_Name[0] indicates the entry in in use. There is an exception about the file name with heading character 0xE5. In this case, 0x05 is set instead.
DIR_Name 字段的第一个字节 DIR_Name[0] 是一个重要数据,用于指示目录条目的状态。 当值为 0xE5 时,表示该条目未被使用(新分配可用)。 当值为 0x00 时,表示该条目未被使用(与 0xE5 相同),此外,在此之后没有分配的条目(在此之后的所有条目中的所有 DIR_Name[0] 也被设置到 0)。 DIR_Name[0] 中的任何其他值表示正在使用的条目。 标题字符为 0xE5 的文件名有一个例外。 在这种情况下,改为设置 0x05。
DIR_Name field is a 11-byte string and divided in two parts, body and extension. The file name is stored in 8-byte body + 3-byte extension. The period in the file name to separate body and exitension is removed on the directory entry. If any part of the name does not fit to the part, rest bytes in the part is filled with spaces (0x20). The code page used for the file name depends on the system.
DIR_Name 字段是一个 11 字节的字符串,分为两部分,正文和扩展。 文件名以 8 字节正文 + 3字节扩展名存储。 在目录条目上,文件名中用于分隔正文和扩展名的句点要删除。 如果名称的任何部分与该部分不匹配,则该部分中的剩余字节用空格(0x20)填充。文件名使用的代码页取决于系统。
FileName DIR_Name[] Description
"FILENAME.TXT" "FILENAMETXT" Dot is removed.
"DOG.JPG" "DOG JPG" Each part is padded with spaces.
"file.txt" "FILE TXT" Each character is upper-case converted.
"蜃気楼.JPG" "・気楼 JPG" The first byte of "蜃", 0xE5, is replaced with 0x05
"NOEXT" "NOEXT " No extension
".cnf" (illegal) Any name without body is not allowed
"new file.txt" (illegal) Space is not allowed.
"file[1].2+2" (illegal) [ ] + are not allowed.
"longext.jpeg" (illegal) Out of 8.3 format.
"two.dots.txt" (illegal) Out of 8.3 format.
Allowable charactes for the file name are 0~9 A~Z ! # $ % & ’ ( ) - @ ^ _ ` { } ~ and extended characters (\x80 - \xFF). Lower-case characters (a-z) appeared in the input file name are replaced with upper-case characters prior to matching and recording. As for the extended characters, there are many differnce on the replacement between each system, such as ä→Ä (CP852) and ä→A (CP850). Therefore, using any extended character can cause compatibility problem in the different systems (e.g. file open failur). As for the extended characters on the Japanese environment, refer to the Compatibility described below.
文件名的允许字符是 0~9 A~Z ! # $ % & ’ ( ) - @ ^ _ ` { } ~ 和扩展字符(\x80 - \xFF)。 在匹配和记录之前,输入文件名中出现的小写字符(a-z)将替换为大写字符。 至于扩展字符,每个系统之间的替换有很多不同,例如ä→Ä(CP852)和ä→A(CP850)。 因此,使用任何扩展字符都可能导致不同系统中的兼容性问题(例如文件打开失败)。 至于日语环境中的扩展字符,请参阅下面描述的兼容性。
Every file names in a directory is unique each other. Any other enrty with the same name never exists. DIR_Attr field indicates the attribute of the entry.
目录中的每个文件名彼此都是唯一的。 任何其他具有相同名称的条目永远不存在。 DIR_Attr 字段指示条目的属性。
File attribute
Flag 标志 | Meaning 含义 |
---|---|
ATTR_READ_ONLY | Read-only File. Any changes to the file or delete should be rejected. 只读文件。对文件的任何更改或删除都应被拒绝。 |
ATTR_HIDDEN | Normal directoly listing should not show this file. (system dependent) 正常的目录列表不应显示此文件。 (取决于系统) |
ATTR_SYSTEM | Indicates this is an system file. (system dependent) 表示这是一个系统文件。 (取决于系统) |
ATTR_DIRECTORY | Indicates this is a container of a directory. 表示这是目录的容器。 |
ATTR_ARCHIVE | This is for backup utilities. Set by FAT driver on new creation, modification or renaming to the file is made. The backup utilities able to easily find the file to be backed up and it clears the attribute after the back up process.这是用于备份实用程序的。在创建、修改或重命名文件时由FAT驱动程序设置。备份实用程序能够轻松找到要备份的文件,并在备份过程之后清除该属性。 |
ATTR_VOLUME_ID | An entry with this attribute has the volume label of the volume. Only one entry can be exist in the root directory. DIR_FstClusHI, DIR_FstClusLO and DIR_FileSize field must be always zero. Some system may set ATTR_ARCHIVE, but it has no meaning. 具有此属性的条目具有卷的卷标签。根目录中只能存在一个条目。DIR FstClusHI、DIR FstClusLO 和 DIR FileSize 字段必须始终为零。一些系统可能会设置 ATTR_ARCHIVE,但它没有任何意义。 |
ATTR_LONG_NAME | This combination of attributes indicates the entry is a part of long file name. Details are described below.这种属性组合表明条目是长文件名的一部分。细节如下所述。 |
Directory Operations 目录操作
Creating File 创建文件
To create a file, FAT driver finds a free entry in the directory to create in. If no free entry is found in the directry, stretch the directry a cluster to allocate a new free entry, but size of a directory cannot exceed 2 MB (65536 entries). Size of static directory (root directory on the FAT12/16 volume) is fixed and cannot be changed. The new entry has its name in the DIR_Name, ATTR_ARCHIVE flag in the DIR_Attr and DIR_FstClusHI, DIR_FstClusLO, DIR_FileSize has 0 for the initial value. When any data is written to the file and file size changed form 0, a new cluster chain is created and the first cluster numner is stored to DIR_FstClusHI, DIR_FstClusLO. The cluster chain is streached as file size increse.
要创建文件,FAT 驱动程序会在要创建的目录中找到一个空闲条目。如果在目录中找不到空闲条目,则将目录扩展一个簇,以分配一个新的空闲条目,但是目录的大小不能超过 2 MB (65536个条目)。 静态目录的大小( FAT12/16 卷上的根目录)是固定的,不能更改。 新条目的名称在 DIR_Name,DIR_Attr 中的 ATTR_ARCHIVE 标志和 DIR_FstClusHI,DIR_FstClusLO,DIR_FileSize 的初始值为 0。 当任何数据写入文件并且文件大小从 0 改变时,会创建一个新的簇链,并且第一个簇编号会存储到 DIR_FstClusHI,DIR_FstClusLO。随着文件大小的增加,簇链被拉伸。
Creating Sub-directory 创建子目录
To create a sub-directory, FAT driver creates a directory entry as creating a file. The entry needs to have ATTR_DIRECTORY attribute. The sub-directry has no size information and DIR_FileSize field must be always zero. A cluster is initially allocated to the sub-directory and the cluster number is set to the DIR_FstClusHI, DIR_FstClusLO field. Each entries in the cluster is initialized to zero. When the directory table gets full, the cluster chain is stretched and cluster is initialized to zero. The maximum length of a direcotry is 2 MB (64 K entries).
要创建子目录,FAT 驱动程序会创建一个目录条目作为创建文件。 该条目需要具有 ATTR_DIRECTORY 属性。 子目标没有大小信息,DIR_FileSize 字段必须始终为零。 最初将簇分配给子目录,并将簇号设置到 DIR_FstClusHI,DIR_FstClusLO 字段。 簇中的每个条目都初始化为零。 当目录表变满时,将拉伸簇链并将簇初始化为零。 目录的最大长度为 2 MB(64 K条目)。
Sub-directory has two special entries (dot entry) at top of the directory, DIR[0] as ". " and DIR[1] as "… ". These entries have ATTR_DIRECTORY attribute, however, they do not have any cluster but point another directory’s cluster instead. “.” entry points this directoy and “…” entry points the parent directory. If the parent directory is the root directory, set zero to the DIR_FstClusHI, DIR_FstClusLO field even if at FAT32 volume.
子目录在目录顶部有两个特殊条目(点条目),DIR[0] 为 “ . ”,DIR[1] 为 “ … ”。 这些条目具有 ATTR_DIRECTORY 属性,但是,它们没有任何簇,而是指向另一个目录的簇。 “ . ” 入口指向该目录和 “…” 入口指向父目录。 如果父目录是根目录,则将 DIR_FstClusHI,DIR_FstClusLO 字段设置为 0。即使是在 FAT32 卷上,也是这样。
Deleting File 删除文件
To remove a file, set 0xE5 to the DIR_Name[0] to free the entry. If the file has a cluster chain, also the chain needs to be removed from the FAT.
要删除文件,将 DIR_Name[0] 设置为 0xE5 以释放条目。如果文件有簇链,那么也需要从 FAT 中删除该链。
Deleting Sub-directory 删除子目录
It is same as deleting a file. All nodes below the directory needs to be scanned and all files and directories in the directory need to be deleted prior to delete the directory otherwise those objects’ clusters get lost clusters.
这与删除文件是一样的。在删除目录之前,需要扫描目录下的所有节点,并删除目录中的所有文件和目录,否则这些对象的簇将丢失簇。
Volume Label 卷标签
FAT volume can have a its own name called volume label, which is recorded as a directory entry with ATTR_VOLUME_ID attribute in the root directory. The volume label is not a file but only a name of the volume. Its name space is independent of the files and the name can be duplicated with any other file in the directory. Allowable characters for the volume label is similar to the SFN entry but it can contain spaces anywhere the name and cannot contain period.
FAT 卷可以有一个称为卷标的自己的名称,它被记录为根目录中具有 ATTR_VOLUME_ID 属性的目录条目。 卷标不是文件,只是卷的名称。 它的名称空间与文件无关,名称可以与目录中的任何其他文件重复。 卷标的允许字符类似于 SFN 条目,但它可以在名称的任何位置包含空格,并且不能包含句点。
The LFN extension is not applied to the volume label. When any change to the volume label is made, it should be reflected to BS_VolLab, but Windows does not do it. Windows has a problem on the behavior at the volume label beginning with a 0xE5. It does not replace it with 0x05 and the change will have no effect, so that such volume label shoud not be used.
LFN 扩展名未应用于卷标。 如果对卷标签进行了任何更改,则应将其反映到 BS_VolLab,但 Windows 不会这样做。 Windows 在以 0xE5 开头的卷标签上的行为存在问题。 它不会用 0x05 替换它,并且更改将不起作用,因此不应使用此类卷标。
Timestamp 时间戳
There are some fields related to the time and data in the directory entry. Most FAT driver supports only DIR_WrtTime, DIR_WrtDate field which is mandatory to be supported and optional fields are not supprted. The non supporting field should be initialized to zero on creation of entry and do not chane afterwards. The format of the time and date is described as follows:
目录条目中有一些与时间和数据相关的字段。大多数 FAT 驱动程序只支持 DIR_WrtTime, DIR_WrtDate字段,且是必须支持的。其他可选字段可以不用支持。不支持的字段在创建条目时应初始化为零,之后不更改。时间和日期的格式如下所述:
Field name 字段名 | Bit fields BIT 字段 |
---|---|
DIR_WrtDate DIR_CrtDate DIR_LstAccDate | Bit 15-9: Count of years from 1980 in range of from 0 to 127 (1980-2107). 从1980年开始的年数从0到127(1980-2107)。 Bit 8-5: Month of year inrange of from 1 to 12. 从1到12的年份。 Bit 4-0: Day of month in range of from 1 to 31. 每月的日期范围为1到31。 |
DIR_WrtTime DIR_CrtTime | Bit 15-11: Hours in range of from 0 to 23. 小时数从0到23。 Bit 10-5: Minutes in range from 0 to 59. 分钟范围从0到59。 Bit 4-0: 2 second count in range of form 0 to 29 (0-58 seconds). 2秒计数,范围从0到29 (0-58秒)。 |
Long File Name 长文件名
When add the long file name (LFN) as a new feature to the FAT filesystem, a backward compatibility with the existing systems is required. Following are concrete examples required.
当将长文件名(LFN)作为新特性添加到FAT文件系统时,需要与现有系统向后兼容。下面是需要的具体例子。
- The existence of LFN needs to be invisible on the existing systems, especially any file API on the MS-DOS and Windows. LFN 的存在需要在现有系统上不可见,尤其是 MS-DOS 和 Windows 上的任何文件 API。
- LFN needs to be located physically near the direcroty entry of the corresponding file to prevent bad effect to the performance. LFN 需要物理上位于相应文件的目录条目附近,以防止对性能产生不良影响。
- If disk utility found the LFN information recorded somewhere on the FAT volume, the filesystem needs to keep sanity and be not affected. 如果磁盘实用程序发现在 FAT 卷上某处记录了 LFN 信息,则文件系统需要保持健全并且不受影响。
To achieve these requirement, LFN information is recorded as directory entry with a special attribute. As described above, the attribute for the LFN entry (ATTR_LONG_NAME) is defined in combination of existing attribute bits (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID), and mask value (ATTR_LONG_NAME_MASK = ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY | ATTR_ARCHIVE) is also defined. When DIR_Attr masked with (ATTR_LONG_NAME_MASK matched with ATTR_LONG_NAME, the entry is an LFN entry and its field is defined as below.
为了达到这些要求,LFN 信息被记录为具有特殊属性的目录条目。 如上所述,LFN 条目(ATTR_LONG_NAME)的属性是由现有属性位(ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)和掩码值(ATTR_LONG_NAME_MASK = ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID | ATTR_DIRECTORY | ATTR_ARCHIVE)的组合定义的。 也定义了。 当 DIR_Attr 被屏蔽时ATTR_LONG_NAME_MASK 与 ATTR_LONG_NAME 匹配,该条目是 LFN 条目,其字段定义如下。
Directory entry structuer for LFN
Field name 字段名 | Offset 偏移 | Size 大小 | Description 描述 |
---|---|---|---|
LDIR_Ord | 0 | 1 | Sequence number (1-20) to identify where this entry is in the sequence of LFN entries to compose an LFN. One indicates the top part of the LFN and any value with LAST_LONG_ENTRY flag (0x40) indicates the last part of the LFN. 序列号(1-20),用于标识此条目在 LFN 条目序列中的位置,以组成 LFN。 一个表示 LFN 的顶部,任何带有 LAST_LONG_ENTRY 标志的值(0x40)表示 LFN 的最后一部分。 |
LDIR_Name1 | 1 | 10 | Part of LFN from 1st character to 5th character. LFN 的一部分,从第 1 个字符到第 5 个字符。 |
LDIR_Attr | 11 | 1 | LFN attribute. Always ATTR_LONG_NAME and it indicates this is an LFN entry. LFN 属性。 始终是 ATTR_LONG_NAME,它表示这是 LFN 条目。 |
LDIR_Type | 12 | 1 | Must be zero. 必须是 0 |
LDIR_Chksum | 13 | 1 | Checksum of the SFN entry associated with this entry. 与此条目关联的 SFN 条目的校验和。 |
LDIR_Name2 | 14 | 12 | Part of LFN from 6th character to 11th character. LFN 的一部分,从第 6 个字符到第 11 个字符。 |
LDIR_FstClusLO | 26 | 2 | Must be zero to avoid any wrong repair by old disk utility. 必须为零,以避免旧磁盘工具的任何错误修复。 |
LDIR_Name3 | 28 | 4 | Part of LFN from 12th character to 13th character. LFN 的一部分,从第 12 个字符到第 13 个字符。 |
LFN entry is always associated with the corresponding SFN entry in order to add LFN to the file. LFN entries never exist independent of SFN. Therfore each file has only SFN or both of SFN and LFN. LFN entry has only name information in it and nothing else about the file. If an LFN entry without association with the SFN entry is exist, such stray LFN entry is invalid and considered garbage. This is for backward compatibility with old system. If an LFN is given to the file, the LFN is the primary name of the file and the SFN is an alternative. Old system without support of LFN does not recognize LFN entry, but it can access with SFN. LFN system can access the file with LFN or SFN. Following table shows how the set of LFN and SFN is recorded on the directory.
LFN 条目始终与相应的 SFN 条目相关联,以便将 LFN 添加到文件中。 LFN 条目从不独立于 SFN 存在。 因此,每个文件只有 SFN 或者 SFN 和 LFN。 LFN 条目只包含其中的名称信息,而没有关于该文件的任何其他信息。 如果存在没有与 SFN 条目关联的 LFN 条目,则这种杂散 LFN 条目无效并被视为垃圾。 这是为了向后兼容旧系统。 如果为文件指定了LFN,则 LFN 是文件的主要名称,SFN 是另一种选择。 不支持 LFN 的旧系统无法识别 LFN 条目,但可以使用 SFN 进行访问。 LFN 系统可以使用 LFN 或 SFN 访问文件。 下表显示了如何在目录中记录 LFN 和 SFN 集。
Association of LFN “MultiMediaCard System Summary.pdf” with a file
Location | First byte | Name field | Attribute | Content |
---|---|---|---|---|
DIR[N-3] | 0x43 | ary.pdf | –VSHR | LFN 3rd part (lfn[26…38]) |
DIR[N-2] | 0x02 | d System Summ | –VSHR | LFN 2nd part (lfn[13…25]) |
DIR[N-1] | 0x01 | MultiMediaCar | –VSHR | LFN 1st part (lfn[0…12]) |
DIR[N] | ‘M’ | MULTIM~1PDF | A----- | Associated SFN entry |
If the LFN is longer than 13 characters, it is divided into some LFN entries. The maximum name length for LFN is 255, so that an LFN occupies upto 20 LFN entries. LFN is put on the directory at just before the associated SFN entry. For the example shown above, an LFN with 33 character in length consist of 3 LFN entries that have 0x43, 0x02, 0x01 in LDIR_Ord. The character code used for the LFN is Unicode in UTF-16 encoding while the character code for SFN is ANSI/OEM code in local code page depends on the system. If the last part does not fit 13 characters, it is terminated with a null character (U+0000) and rest of name field must be filled with U+FFFF. LDIR_Ord must start at 1 and be recorded in descending order. The block of LFN+SFN are recorded on a contiguous entries. If any of these condition about LFN entry is not met, the LFN is invalid any longer.
如果 LFN 超过 13 个字符,它将被分成一些 LFN 条目。LFN 的最大名称长度是 255,因此一个 LFN 最多可以容纳 20 个 LFN 条目。LFN 就在相关的 SFN 条目的前面。对于上面显示的示例,长度为 33 个字符的 LFN 由 3 个 LFN 条目组成,它们在 LDIR_Ord 中具有 0x43、0x02、0x01。LFN 使用的字符代码是 UTF-16 编码的 Unicode,而 SFN 的字符代码是本地代码页中的 ANSI/OEM 代码,具体取决于系统。如果最后一部分不适合 13 个字符,则以空字符(U+0000)结束,其余的名称字段必须用 U+FFFF 填充。LDIR_Ord 必须从 1 开始,并按降序记录。LFN+SFN 的区块记录在相邻的条目上。如果不满足关于 LFN 条目的任何一个条件,则 LFN 不再有效。
如果文件的名称是 Unicode 或不遵循 MS-DOS 8.3 命名约定,则会分配其他目录条目来存储长文件名:补充条目位于文件的主条目之前。 下图显示了一个名为 “The quick brown fox.” 的文件的示例目录条目:系统创建了8.3 格式的名称 THEQUI~1 FOX (在目录条目中没有看到 “ . ” 因为它被认为是在第八个字符之后)并且使用了两个以上的目录条目来存储Unicode 长文件名; 图中的每一行由 16 个字节组成。
Furthermore, a check sum is used to make sure of relevance between LFN and SFN. Each LFN entry has a check sum of associated SFN in LDIR_Chksum. The check sum is generated in the algorithm shown below.
此外,校验和用于确保 LFN 和 SFN 之间的相关性。 每个 LFN 条目都具有 LDIR_Chksum 中相关 SFN 的校验和。 校验和在下面显示的算法中生成。
uint8_t create_sum (const DIR* entry)
{
int i;
uint8_t sum;
for (i = sum = 0; i < 11; i++) { /* Calculate sum of DIR_Name[] field */
sum = (sum >> 1) + (sum << 7) + entry->DIR_Name[i];
}
return sum;
}
If any check sum in the LFN entries does not match, the LFN is invalid. This is to prevent wrong association due to any changes (delete, create or rename) to the direcotry by the non-LFN system. However, stray LFN entries continue to occupy the directory and the disk usage gets worse. This will be a problem at the fixed length directory (root directory on FAT12/16 volume). These garbage entries are removed by disk utirities.
如果 LFN 条目中的任何校验和不匹配,则 LFN 无效。 这是为了防止由于非 LFN 系统对目录的任何更改(删除,创建或重命名)导致的错误关联。 但是,杂散 LFN 条目继续占用目录,磁盘使用情况变得更糟。 这将是固定长度目录(FAT12/16 卷上的根目录)中的问题。 这些垃圾条目被磁盘删除。
Namespace 命名空间
Short File Name 短文件名
SFN, often called the 8.3 format name, is a traditional style file name originally used on the MS-DOS in format of body (1-8 character) plus optional extension (1-3 characters). These two parts are separated with a dot (.). The allowable charactes for the SFN are ASCII alphanumerics, non-ASCII characters (\x80 - \xFF) and some ASCII marks ($ % ’ - _ @ ~ ` ! ( ) { } ^ # &).
SFN,通常称为 8.3 格式名称,是最初在 MS-DOS 上使用的传统样式文件名,其格式为 SFN Body(1-8个字符). SFN Extension(1-3个字符)。 这两个部分用点(.)分隔。 SFN 的允许字符是 ASCII 字母和数字,非 ASCII 字符(\ x80 - \ xFF)和一些 ASCII 标记($%’ - _ @〜!(){} ^#&)。如下图所示:
SFN is stored in the SFN entry in OEM code set (used on MS-DOS) depends on the locale. Lower-case character in the file name is converted to upper-case and then stored or matched, so that the case information of SFN file name is lost.
SFN 存储在 OEM 代码集中的 SFN 条目中(在 MS-DOS 上使用),这取决于系统区域设置。将文件名中的小写字符转换为大写字符,然后存储和匹配,从而丢失 SFN 的大小写信息。
Long File Name 长文件名
Length of LFN can be upto 255 characters. The allowable characters for the LFN are white space and some ASCII marks (+ , ; = [ ]) in addition to the SFN characters. Dots can be embedded anywhere in the file name except the trailing dots and spaces are truncated off on the file API. Leading spaces and dots are valid but some user interface, such as Windows common dialog, rejects such file name.
LFN 的长度可以达到 255 个字符。 除了 SFN 字符外,LFN 还允许的字符是空格和一些 ASCII 标记(+,;=[])。点可以嵌入文件名的任何位置,但文件 API 中的尾随点和空格会被截断。前导空格和点是有效的,但是一些用户界面,如 Windows 公共对话框,拒绝这样的文件名。
LFN is stored in the LFN entry as is without any process like SFN. Character code used by LFN is Unicode.
LFN 存储在 LFN 条目中,无需进行大小写转换。 LFN 使用的字符编码是 Unicode。
Because different character codes are used by SFN (OEM code set) and LFN (Unicode), generic implementation needs to convert those codes. This is not the matter on the OEM code is single byte code, however, when the OEM code page is in double byte character set (DBCS), a huge (several hundreds KB) conversion table is needed, so that it is difficult to implement LFN in the small embedded systems with a limited memory.
由于 SFN(OEM 代码集)和 LFN(Unicode)使用不同的字符代码,因此通常的实现中需要转换这些代码。 OEM 是单个字节编码并没有什么问题,但是,当 OEM 代码页是双字节字符集(DBCS)时,需要一个巨大的(几百KB)转换表,因此在具有有限的内存的小型嵌入式系统中很难实现 LFN 。
Name Matching 名称匹配
There are two format of file names, LFN and SFN. Both file name for the file is generated at a time. A file name is unique in the directory and never matchs with any name no matter between different formats. LFN can contain lower-case characters and matched in case insensitive, so that “LongFileName.Txt”, “longfilename.txt”, “LONGFILENAME.TXT” these three names match each other. Therfore name matching on directory search are done in case insensitive.
文件名有两种格式,LFN 和 SFN。文件的两个文件名同时生成。文件名在目录中是唯一的,并且即使在不同格式之间都不会与任何名称匹配。 LFN 可以包含小写字符并且在不区分大小写的情况下匹配,因此“LongFileName.Txt”,“longfilename.txt”,“LONGFILENAME.TXT” 这三个名称相互匹配。 目录搜索中的名称匹配是在不区分大小写的情况下完成的。
When search a file with a file name that fits SFN format, Both LFNs and SFNs in the directory are checked for match. When search a file with a file name out of SFN format, only LFNs are checked for match.
当搜索具有适合 SFN 格式的文件名的文件时,将检查目录中的 LFN 和 SFN 是否匹配。 搜索文件名超出SFN 格式的文件时,仅检查 LFN 是否匹配。
The character code set on the file API would be either OEM code or Unicode. When it is in OEM code, some characters in the LFN may not able to be converted to OEM code. In this case, FAT driver should return SFN instead.
文件 API 中设置的字符代码可以是 OEM 代码,也可以是 Unicode 代码。当使用 OEM 代码时,LFN 中的一些字符可能无法转换为 OEM 代码。在这种情况下,FAT 驱动程序应该返回 SFN。
Generating SFN 生成 SFN
On the LFN system, any fine name given to the file API needs to be used as LFN. SFN needs to be generated from the file name and the FAT driver should not allow to specify LFN and SFN individually. This is to avoid any confusion about file name between uses and applicaations, to achive consistency in the file name of a file and to avoid name conflict and any troublesome. SFN is generated as body(+numeric-tail)(+extension) in following procedure.
在支持 LFN 的系统上,传递给文件 API 的任何良好名称都需要被视为 LFN。SFN 需要从输入文件名生成,FAT 驱动程序不应该允许单独指定 LFN 和 SFN。这是为了避免用户和应用程序之间文件名的混淆,实现文件名的一致性,避免文件名冲突和一些麻烦。SFN 作为 body(+ number -tail)(+extension) 在以下过程中生成。
- Trailing dots and spaces are truncated off if exist. (a precondition of file name on the FAT file system) 如果存在尾随点和空格,则将其截断。(FAT文件系统文件名的先决条件)
- If any space is exist, remove it and set lossy conversion flag. 如果存在任何空格,请删除它并设置有损转换标志。
- If any leading dot is exist, remove it and set lossy conversion flag. 如果存在任何前导点,请将其删除并设置有损转换标志。
- If two or more dots are exist, remove all dots except for last one and set lossy conversion flag. 如果存在两个或多个点,则删除除最后一个点以外的所有点并设置有损转换标志。
- If any character not allowed for SFN is exist, replace it with an underscore () and set lossy conversion flag. 如果存在任何不允许存在SFN的字符,请将其替换为下划线()并设置有损转换标志。
- Lower-case characters including non-ASCII characters are converted into upper-case. 包含非 ASCII 字符的小写字符将转换为大小写。
- When character code on the API is Unicode, convert it to OEM code set string. If any Unicode character could not be converted to OEM code, replace it with an underscore and set lossy conversion flag. 当 API 上的字符代码是 Unicode 时,将其转换为 OEM 代码集字符串。 如果无法将任何一个 Unicode 字符转换为 OEM 代码,请将其替换为下划线并设置有损转换标志。
- Fill 11-byte SFN output buffer with spaces. 用空格填充11字节SFN输出缓冲区。
- Creating SFN body. Copy from top of the LFN to the SFN body part in byte-by-byte until end of LFN, a dot is read or SFN body is full. If the LFN body is longer than 8 bytes, set lossy conversion flag. 创建 SFN 正文。 从 LFN 的顶部逐字节地复制到 SFN 主体部分,直到 LFN 结束或者找到点或者 SFN 主体已满。 如果 LFN 主体长于 8 个字节,则设置有损转换标志。
- Creating SFN extension. If a dot is exist, copy from next of dot to the SFN extension part in byte-by-byte until end of LFN or SFN extension is full. If the LFN extensiton is longer than 8 bytes, set lossy conversion flag. 创建 SFN 扩展。 如果存在点,则从点的下一个位置逐字节复制到 SFN 扩展部分,直到 LFN 结束或 SFN 扩展已满。 如果 LFN 扩展长度超过 3 个字节,请设置有损转换标志。
Here an SFN as body(+extension) is created. If lossy conversion flag is set, it means the input file name does not fit 8.3 format and is not used for match. The lossy converted SFN cannot be used for new file creation. It needs to put a numeric-tail to the body to make it be unique. The format of the numeric-tail is ~n (n is 1-6 digit decimal). The value needs to be changed if the SFN conflicts with an existing SFN entry in the directory. It is typically searched in the order from 1, but it depends on implementation. For example, Windows NT family uses any hash value at 5th trial.
以上步骤创建一个 SFN 的主体部分(+ 扩展名)。 如果设置了有损转换标志,则表示输入文件名不是 8.3 格式,不能用于匹配和记录。 有损转换的 SFN 不能用于新文件创建。 它需要在主体上添加一个数字尾部,以使 SFN 在目录中唯一。 数字尾的格式是 ~n(n是1-6位十进制数)。 需要截断名称正文以添加数字尾部。 通常以 〜1 的顺序搜索唯一名称,但这取决于实现。 例如,Windows NT 系列在第 5 次试用时使用了一些哈希值。
Suppressing LFN Entry 抑制 LFN 条目
When the file name is in 8.3 format, generated SFN becomes same as the LFN (except for upper-case conversion). In this case, the LFN entry is suppressed and not created if the follwing conditions each is true.
当文件名为 8.3 格式时,生成的 SFN 与 LFN 相同(大小写转换除外)。 在这种情况下,如果下面的两个条件都为真,则可以抑制 LFN 条目,而不创建 LFN 条目。
- Does not contain lower-case character, 不包含任何小写字符,
- and does not contain any non-ASCII character. 并且不包含任何非 ASCII 字符。
For example, “HELLO.TXT” is the case. On the Window NT family, also following condition is tested.
例如,“HELLO.TXT” 就是这种情况。 在 Window NT 系列上,还测试了以下条件。
- Either or both of body and extension contains any lower-case character, 正文和扩展中的任何一个或两个都包含任何小写字符,
- and both of body and extension are not mixed-case, 正文和扩展都不是大小写混合的,
- and does not contain any non-ASCII character. 并且不包含任何非 ASCII 字符。
If it is the case, lower capital information is stored in the DIR_NTRes of SFN entry and the LFN entry is suppressed. The file name satisfies this condition, such as “lower12.dll”, “system32”, “FDCMD.exe”, is very common for most existing files. This enables to save the space of direcrory. On the some systems, such as Windows 9X family, DIR_NTRes field is not supported and these entries are recognized as old SFN entries and the files will appear in the directory listing as “LOWER12.DLL”, “SYSTEM32”, “FDCMD.EXE”. It is not a problem because name matching is done in case insensitive on the FAT file system. However, it can confuse some Unix based application running on the Windows 9X family OS when it refers a volume written by Window NT family OS.
如果是以上说的这种情况,则较低的资本信息记录在 SFN 条目的 DIR_NTRes 中,并且 LFN 条目被抑制。 文件名满足此条件,例如 “lower12.dll”,“system32”,“FDCMD.exe”,对于大多数现有文件来说非常常见。 这样可以节省可怕的空间。 在某些 LFN 感知系统(如 Windows 9X 系列)上,不支持 DIR_NTRes 字段,这些条目被识别为旧的 SFN 条目,文件将在目录列表中显示为 “LOWER12.DLL”,“SYSTEM32”,“FDCMD.EXE”。 这不是问题,因为名称匹配是在 FAT 文件系统不区分大小写的情况下完成的。 但是,当它引用 由Window NT 系列操作系统编写的卷时,它可能会混淆在 Windows 9X 系列操作系统上运行的某些基于 Unix 的应用程序。
Compatibility 兼容性
Non LFN Aware System 非 LFN 感知系统
The support of LFN is most important on the fixed disks, however it is supported on removable media as well. The removavle media is shared by various systems with or without support for LFN, so that the downward compatibility is important for the implementation of LFN and it provides support for LFN without breaking compatibility with the existing FAT format. An FAT volume with any LFN exists can be read by down level systems without any compatibility problems. An exsisting FAT volume does not need to go through any comversion process prior to start using LFN and any current files remain not modified. The LFN entry is added on a long name is created. When rename a current file with LFN, the SFN entry will be moved within the directory to create an entry block. The LFN entries are hidden at the generic file APIs on the down level systems and it does not cause any problem on geneic use. The user can read any file with 8.3 format name and put a new file without any side effect.
LFN 的支持在固定磁盘上最为重要,但它也支持可移动媒体。 在支持或不支持 LFN 的情况下,各种系统共享可移除媒体,因此向下兼容性对于 LFN 的实现是重要的,并且它提供对 LFN 的支持而不破坏与现有 FAT 格式的兼容性。 具有任何 LFN 的 FAT 卷可以由下级系统读取而没有任何兼容性问题。 在开始使用 LFN 之前,现有的 FAT 卷不需要经历任何修改过程,并且任何当前文件都不会被修改。 LFN 条目添加在创建的长名称上。 使用 LFN 重命名当前文件时,SFN 条目将在目录中移动以创建条目块。 LFN条目隐藏在下层系统的通用文件API中,并且不会对基因使用造成任何问题。 用户可以使用 8.3 格式名称读取任何文件,并放置一个没有任何副作用的新文件。
Down level systems do not aware of existence of LFN, so that some LFN entry can be broken by a directory operation. For instance, when a file with LFN is renamed, LDIR_Chksum in the LFN entries gets mismatch and as the result the LFN will be lost. Renaming or deleting volume label can break some LFN entry as well. This is unfortunate, but the file data itself is kept safe.
低层系统不知道LFN的存在,因此一些LFN条目可以被目录操作破坏。 例如,当重命名具有LFN的文件时,LFN条目中的LDIR_Chksum变得不匹配,结果LFN将丢失。 重命名或删除卷标也可以打破一些LFN条目。 这很不幸,但文件数据本身是安全的。
Upper-case Conversion of Japanese MS-DOS 日语 MS-DOS 的大写转换
Upper-case conversion for SFN is applied to non-ASCII characters as well. However, it is not applied to non-ASCII characters on the Japanese MS-DOS and non-ASCII characters are stored without upper-case conversion. It is changed at Windows NT family and it creates SFN entry with upper-case conversion for all charactres. As the result, it brings a serious compatibility problem on us. For instance, create a file “Fat.TXT” (name body is non-ASCII full-width character) on the MS-DOS. And then mount the volume on the Windows XP, and the file is no longer accessible. This is because Windows NT family finds the SFN entry with upper-case converted name “FAT.TXT” and it never matches the SFN created by MS-DOS. The only workaround is to avoid using such file name. Also Windows 9X family creates the SFN without upper-case converson, but it is not the problem because LFN entry is created and it can be opened on the Windows NT family.
SFN 的大写转换也适用于非ASCII字符。 但是,它不适用于日语MS-DOS上的非ASCII字符,并且存储非ASCII字符而不进行大写转换。 它在Windows NT系列中进行了更改,它为所有字符创建了带大写转换的SFN条目。 结果,它给我们带来了严重的兼容性问题。 例如,在MS-DOS上创建一个文件“Fat.TXT”(名称正文是非ASCII全角字符)。 然后在Windows XP上安装卷,则无法再访问该文件。 这是因为Windows NT系列找到具有大写转换名称“FAT.TXT”的SFN条目,它永远不会匹配MS-DOS创建的SFN。 唯一的解决方法是避免使用此类文件名。 此外,Windows 9X系列创建没有大写转换的SFN,但这不是问题,因为创建了LFN条目并且可以在Windows NT系列上打开它。
Differnet OEM Code Page 不同的OEM代码页
Some OEM code pages are in DBCS. The trailing byte of a double-byte character can match any illigal character for file name, especially most FAT driver uses \ (\x5C) for directory separator for the path name. If the file name contains such character, the file will not able to be accessed on the system with SBCS. There is similar ploblem between SBCS systems due to upper-case conversions of non-ASCII characters which differ between each SBCS systems. When exchange files between the systems with different code page, any file name with non-ASCII character should not be used.
某些OEM代码页位于DBCS中。 双字节字符的尾随字节可以匹配文件名的任何illigal字符,尤其是大多数FAT驱动程序使用\(\ x5C)作为路径名的目录分隔符。 如果文件名包含此类字符,则无法在具有SBCS的系统上访问该文件。 由于每个SBCS系统之间不同的非ASCII字符的大写转换,SBCS系统之间存在类似的问题。 在具有不同代码页的系统之间交换文件时,不应使用任何具有非ASCII字符的文件名。
There is no problem on the LFN because file name is stored on the directory in Unicode. However, when character code on the file API is OEM code (this is incomplete support for LFN), some problems related to different code page can occuer.
LFN没有问题,因为文件名以Unicode格式存储在目录中。 但是,当文件API上的字符代码是OEM代码时(这是对LFN的不完全支持),可能会出现与不同代码页相关的一些问题。
Mac OS X
Mac OS X supports the file names with trailing dots or spaces and it can mount the FAT volume as well. However, such file name is not allowed on the FAT volume. If a file to be created on the FAT volume is such name, Mac OS X replace the last character with an escape character (space:U+F028, dot:U+F029). Application program needs to consider it when exchange the file between Mac and another systems via a removable media.
Physical Drive Partitioning 物理驱动器分区
This is not related to the FAT filesystem, but it is a basis of disk usage. You need to know when write a FAT driver for embedded systems.
这与FAT文件系统无关,但它是磁盘使用的基础。 您需要知道何时为嵌入式系统编写FAT驱动程序。
To use the huge disk space of harddisk drive efficiently, it is often used in divided into some partitions. For example, divide a 10 GB harddisk into 3 partitions, 1, 3 and 6 GB, and create volumes for swap, system and data. For generic use, only one partition is created and used in one volume per disk drive.
为了有效地利用硬盘驱动器的巨大磁盘空间,常常将其划分为若干分区。例如,将一个10gb的硬盘划分为3个分区,1、3和6 GB,并为交换、系统和数据创建卷。对于一般使用,每个磁盘驱动器在一个卷中只创建和使用一个分区。
There are two partitioning rules, FDISK format and SFD format. The FDISK format is usually used for harddisk and memory card. It can divide a physical drive into one or more partitions with a partition table put on the MBR (maser boot record, the first sector of the physical drive). The SFD (super-floppy disk) format is non-partitioned disk format. The volume starts at the first sector of the physical drive without any disk partitioning. It is usually used for floppy disk, Microdrive, optical disk and most type of super-floppy media. Some systems support only either one of the two formats and the other is not supported.
有两种分区规则,FDISK格式和SFD格式。 FDISK格式通常用于硬盘和存储卡。 它可以将物理驱动器划分为一个或多个分区,并将分区表放在MBR上(maser引导记录,物理驱动器的第一个扇区)。 SFD(超级软盘)格式是非分区磁盘格式。 卷从物理驱动器的第一个扇区开始,没有任何磁盘分区。 它通常用于软盘,Microdrive,光盘和大多数类型的超软盘介质。 某些系统仅支持两种格式中的一种,另一种不支持。
MBR and Partition table
Field name | Offset | Size | Description |
---|---|---|---|
MBR_bootcode | 0 | 446 | Boot program. Depends on the system. Filled with zeros when not used. |
MBR_Partation1 | 446 | 16 | Partition table enrty 1. Indicates partition type and status. |
MBR_Partation2 | 462 | 16 | Partition table enrty 2. |
MBR_Partation3 | 478 | 16 | Partition table enrty 3. |
MBR_Partation4 | 494 | 16 | Partition table enrty 4. |
MBR_Sig | 510 | 2 | 0xAA55. Indicates this is a valid MBR. |
Following table shows the field of partition table entry and upto four entry can be recorded in the MBR. This means a storage device can be divided four partitions. There is a type of partition which can contain some partitions in it, but for details of it, prease refer to others.
Partition table entry
Field name | Offset | Size | Description |
---|---|---|---|
PT_BootID | 0 | 1 | Boot indicator. Not bootable (0x00) or Bootable (0x80). Bootable is to make the system boots from this partition, but it is system dependent. Only one partition can be set to bootable. |
PT_StartHd | 1 | 1 | Indicates head number of partition start sector in CHS form (0 - 254). |
PT_StartCySc | 2 | 2 | Indicates cylinder number (bit9-0: 0-1023) and sector number in the cylinder (bit15-10: 1-63) of partition start sector in CHS form. |
PT_System | 4 | 1 | Type of this partition. Typical valuse are: 0x00: Blank entry. Any other field must be zero. 0x01: FAT12 (CHS/LBA, < 65536 sectors) 0x04: FAT16 (CHS/LBA, < 65536 sectors) 0x05: Extended partition (CHS/LBA) 0x06: FAT12/16 (CHS/LBA, >= 65536 sectors) 0x07: HPFS/NTFS/exFAT (CHS/LBA) 0x0B: FAT32 (CHS/LBA) 0x0C: FAT32 (LBA) 0x0E: FAT12/16 (LBA) 0x0F: Extended partition (LBA) |
PT_EndHd | 1 | 1 | Indicates head number of partition end sector in CHS form (0 - 254). |
PT_EndCySc | 2 | 2 | Indicates cylinder number (bit9-0: 0-1023) and sector number in the cylinder (bit15-10: 1-63) of partition end sector in CHS form. |
PT_LbaOfs | 8 | 4 | Indicates partition start sector in 32-bit LBA (1 - 0xFFFFFFFF). |
PT_LbaSize | 12 | 4 | Partition size in unit of sector (1 - 0xFFFFFFFF). |
Ecah partition occupy any part of drive without overlapping each other and the first sector of the partition is the VBR. In most case, only first entry is used and rest of entries are left blanked.
There are two formart to express allocation of the partitions, CHS and LBA. Both parameters are stored on the entry. CHS field is used for the drives that have geometry, but this is actually depends on the system. LBA field is used for the drives controled in LBA. If the partition overlaps an area where cannot be expressed in CHA (8 GB and above), CHS field is no longer valid and only LBA field can be used.