分享

exfat文件系统分析

 sdxy 2021-09-23

本文详细分析了exfat文件系统结构,并通过实际数据对exfat文件系统各个字段中的定义进行解释。

目录

1文件系统整体布局

2 -1Master Boot Record(MBR)-MBR分区

2.1 结构

2.2 数据分析

2.3 读取硬盘MBR数据C++语言代码

2-2 GUID Partition Table(GPT)分区

3 ExFAT文件系统卷分布

3.1 Main Boot Region 主引导区

3.1.1 引导扇区(Boot Sector)

3.1.2 扩展引导扇区(Extended Boot Sector)

3.1.3 OEM参数(OEM Parameters)

3.1.4 引导校验和(ExFAT Boot Checksum)

4 FAT Region FAT表区

5 簇位图文件

6 大写字符文件

7 根目录文件项

7.1 卷标目录项

7.2 簇位图文件的目录项

7.3 大写字符文件的目录项

7.4 用户文件的目录项

7.4.1 属性1目录项

7.4.2 属性2目录项

7.4.3 属性3目录项

8 ExFAT文件系统的根目录及子目录的管理

9 删除文件

10 Exfat文件系统元文件大小分配问题


1文件系统整体布局

硬盘有两种分区格式:MBR(Master Boot Record)分区和GPT(GUID Partition Table)分区。MBR磁盘分区支持最大卷为2TB(Terabytes)并且每个磁盘最多有4个主分区(或3个主分区,1个扩展分区和无限制的逻辑驱动器);GPT磁盘分区样式支持最大卷为18 EB(Exabytes)并且每磁盘的分区数没有上限,只受到操作系统限制,Windows最大仅支持128个GPT分区。硬盘是哪种分区可以根据主引导记录(Master Boot Record)中分区类型字段判断,分区类型为“EE”,代表GPT分区。

2 -1Master Boot Record(MBR)-MBR分区

2.1 结构

传统通用的Master Boot Record(MBR)结构

地址

描述

大小/字节

十六进制

十进制

+000hex

+0

引导代码区

446

+1BEhex

+446

第1分区

分区表

16

+1CEhex

+462

第2分区

16

+1DEhex

+478

第3分区

16

+1EEhex

+494

第4分区

16

+1FEhex

+510

55hex

引导结束标志

2

+1FFhex

+511

AAhex

Total size: 446 + 4×16 + 2

512

每个分区格式

偏移量/字节

长度/字节

描述

0x00

1

物理驱动器状态,旧的MBR只接受80H,00H表示不活动的,01H~7FH表示无效

0x01

3

在分区的第一个绝对扇区CHS地址,格式如下

偏移量


1

h7-0

x

x

x

x

x

x

x

x

2

C9-8

s5–0

x

x

x

x

x

x

x

x









3

C7-0

x

x

x

x

x

x

x

x

0x04

1

分区类型

0x05

3

在分区的最后绝对扇区CHS地址,格式同第一个绝对扇区CHS地址

0x08

4

分区中第一个LBA(逻辑块寻址)绝对扇区

0x0C

4

分区扇区数

分区格式有MBR分区和GPT分区,以上分区格式属于MBR。

2.2 数据分析

480G与943G SATA盘 MBR分区数据对比

480G

943G

33 00 8E D0 BC 00 7C 8E  C0 8E D8 BE 00 7C BF 00

06 B9 00 02 FC F3 A4 50  68 1C 06 CB FB B9 04 00

BD BE 07 80 7E 00 00 7C  0B 0F 85 0E 01 83 C5 10

E2 F1 CD 18 88 56 00 55  C6 46 11 05 C6 46 10 00

B4 41 BB AA 55 CD 13 5D  72 0F 81 FB 55 AA 75 09

F7 C1 01 00 74 03 FE 46  10 66 60 80 7E 10 00 74

26 66 68 00 00 00 00 66  FF 76 08 68 00 00 68 00

7C 68 01 00 68 10 00 B4  42 8A 56 00 8B F4 CD 13

9F 83 C4 10 9E EB 14 B8  01 02 BB 00 7C 8A 56 00

8A 76 01 8A 4E 02 8A 6E  03 CD 13 66 61 73 1C FE

4E 11 75 0C 80 7E 00 80  0F 84 8A 00 B2 80 EB 84

55 32 E4 8A 56 00 CD 13  5D EB 9E 81 3E FE 7D 55

AA 75 6E FF 76 00 E8 8D  00 75 17 FA B0 D1 E6 64

E8 83 00 B0 DF E6 60 E8  7C 00 B0 FF E6 64 E8 75

00 FB B8 00 BB CD 1A 66  23 C0 75 3B 66 81 FB 54

43 50 41 75 32 81 F9 02  01 72 2C 66 68 07 BB 00

00 66 68 00 02 00 00 66  68 08 00 00 00 66 53 66

53 66 55 66 68 00 00 00  00 66 68 00 7C 00 00 66

61 68 00 00 07 CD 1A 5A  32 F6 EA 00 7C 00 00 CD

18 A0 B7 07 EB 08 A0 B6  07 EB 03 A0 B5 07 32 E4

05 00 07 8B F0 AC 3C 00  74 09 BB 07 00 B4 0E CD

10 EB F2 F4 EB FD 2B C9  E4 64 EB 00 24 02 E0 F8

24 02 C3 49 6E 76 61 6C  69 64 20 70 61 72 74 69

74 69 6F 6E 20 74 61 62  6C 65 00 45 72 72 6F 72

20 6C 6F 61 64 69 6E 67  20 6F 70 65 72 61 74 69

6E 67 20 73 79 73 74 65  6D 00 4D 69 73 73 69 6E

67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74

65 6D 00 00 00 63 7B 9A  54 AC 76 97 00 00 00 20

21 00 07 FE FF FF 00 08  00 00 00 20 E4 37 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA

33 00 8E D0 BC 00 7C 8E  C0 8E D8 BE 00 7C BF 00

06 B9 00 02 FC F3 A4 50  68 1C 06 CB FB B9 04 00

BD BE 07 80 7E 00 00 7C  0B 0F 85 0E 01 83 C5 10

E2 F1 CD 18 88 56 00 55  C6 46 11 05 C6 46 10 00

B4 41 BB AA 55 CD 13 5D  72 0F 81 FB 55 AA 75 09

F7 C1 01 00 74 03 FE 46  10 66 60 80 7E 10 00 74

26 66 68 00 00 00 00 66  FF 76 08 68 00 00 68 00

7C 68 01 00 68 10 00 B4  42 8A 56 00 8B F4 CD 13

9F 83 C4 10 9E EB 14 B8  01 02 BB 00 7C 8A 56 00

8A 76 01 8A 4E 02 8A 6E  03 CD 13 66 61 73 1C FE

4E 11 75 0C 80 7E 00 80  0F 84 8A 00 B2 80 EB 84

55 32 E4 8A 56 00 CD 13  5D EB 9E 81 3E FE 7D 55

AA 75 6E FF 76 00 E8 8D  00 75 17 FA B0 D1 E6 64

E8 83 00 B0 DF E6 60 E8  7C 00 B0 FF E6 64 E8 75

00 FB B8 00 BB CD 1A 66  23 C0 75 3B 66 81 FB 54

43 50 41 75 32 81 F9 02  01 72 2C 66 68 07 BB 00

00 66 68 00 02 00 00 66  68 08 00 00 00 66 53 66

53 66 55 66 68 00 00 00  00 66 68 00 7C 00 00 66

61 68 00 00 07 CD 1A 5A  32 F6 EA 00 7C 00 00 CD

18 A0 B7 07 EB 08 A0 B6  07 EB 03 A0 B5 07 32 E4

05 00 07 8B F0 AC 3C 00  74 09 BB 07 00 B4 0E CD

10 EB F2 F4 EB FD 2B C9  E4 64 EB 00 24 02 E0 F8

24 02 C3 49 6E 76 61 6C  69 64 20 70 61 72 74 69

74 69 6F 6E 20 74 61 62  6C 65 00 45 72 72 6F 72

20 6C 6F 61 64 69 6E 67  20 6F 70 65 72 61 74 69

6E 67 20 73 79 73 74 65  6D 00 4D 69 73 73 69 6E

67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74

65 6D 00 00 00 63 7B 9A  15 F2 CA 2C 00 00 00 20

21 00 07 FE FF FF 00 08  00 00 00 E8 FF 75 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA

_应该是个随机数,以上两个磁盘的隐藏扇区数均为0x0800,总扇区数分别为0x37E42000、0x75FFE800。

943G 分成多个分区(MBR)的MBR数据

2个

4个

33 00 8E D0 BC 00 7C 8E  C0 8E D8 BE 00 7C BF 00

06 B9 00 02 FC F3 A4 50  68 1C 06 CB FB B9 04 00

BD BE 07 80 7E 00 00 7C  0B 0F 85 0E 01 83 C5 10

E2 F1 CD 18 88 56 00 55  C6 46 11 05 C6 46 10 00

B4 41 BB AA 55 CD 13 5D  72 0F 81 FB 55 AA 75 09

F7 C1 01 00 74 03 FE 46  10 66 60 80 7E 10 00 74

26 66 68 00 00 00 00 66  FF 76 08 68 00 00 68 00

7C 68 01 00 68 10 00 B4  42 8A 56 00 8B F4 CD 13

9F 83 C4 10 9E EB 14 B8  01 02 BB 00 7C 8A 56 00

8A 76 01 8A 4E 02 8A 6E  03 CD 13 66 61 73 1C FE

4E 11 75 0C 80 7E 00 80  0F 84 8A 00 B2 80 EB 84

55 32 E4 8A 56 00 CD 13  5D EB 9E 81 3E FE 7D 55

AA 75 6E FF 76 00 E8 8D  00 75 17 FA B0 D1 E6 64

E8 83 00 B0 DF E6 60 E8  7C 00 B0 FF E6 64 E8 75

00 FB B8 00 BB CD 1A 66  23 C0 75 3B 66 81 FB 54

43 50 41 75 32 81 F9 02  01 72 2C 66 68 07 BB 00

00 66 68 00 02 00 00 66  68 08 00 00 00 66 53 66

53 66 55 66 68 00 00 00  00 66 68 00 7C 00 00 66

61 68 00 00 07 CD 1A 5A  32 F6 EA 00 7C 00 00 CD

18 A0 B7 07 EB 08 A0 B6  07 EB 03 A0 B5 07 32 E4

05 00 07 8B F0 AC 3C 00  74 09 BB 07 00 B4 0E CD

10 EB F2 F4 EB FD 2B C9  E4 64 EB 00 24 02 E0 F8

24 02 C3 49 6E 76 61 6C  69 64 20 70 61 72 74 69

74 69 6F 6E 20 74 61 62  6C 65 00 45 72 72 6F 72

20 6C 6F 61 64 69 6E 67  20 6F 70 65 72 61 74 69

6E 67 20 73 79 73 74 65  6D 00 4D 69 73 73 69 6E

67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74

65 6D 00 00 00 63 7B 9A  15 F2 CA 2C 00 00 00 20

21 00 07 FE FF FF 00 08  00 00 00 00 80 0C 00 FE

FF FF 07 FE FF FF 00 08  80 0C 00 E8 7F 69 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 AA

33 00 8E D0 BC 00 7C 8E  C0 8E D8 BE 00 7C BF 00

06 B9 00 02 FC F3 A4 50  68 1C 06 CB FB B9 04 00

BD BE 07 80 7E 00 00 7C  0B 0F 85 0E 01 83 C5 10

E2 F1 CD 18 88 56 00 55  C6 46 11 05 C6 46 10 00

B4 41 BB AA 55 CD 13 5D  72 0F 81 FB 55 AA 75 09

F7 C1 01 00 74 03 FE 46  10 66 60 80 7E 10 00 74

26 66 68 00 00 00 00 66  FF 76 08 68 00 00 68 00

7C 68 01 00 68 10 00 B4  42 8A 56 00 8B F4 CD 13

9F 83 C4 10 9E EB 14 B8  01 02 BB 00 7C 8A 56 00

8A 76 01 8A 4E 02 8A 6E  03 CD 13 66 61 73 1C FE

4E 11 75 0C 80 7E 00 80  0F 84 8A 00 B2 80 EB 84

55 32 E4 8A 56 00 CD 13  5D EB 9E 81 3E FE 7D 55

AA 75 6E FF 76 00 E8 8D  00 75 17 FA B0 D1 E6 64

E8 83 00 B0 DF E6 60 E8  7C 00 B0 FF E6 64 E8 75

00 FB B8 00 BB CD 1A 66  23 C0 75 3B 66 81 FB 54

43 50 41 75 32 81 F9 02  01 72 2C 66 68 07 BB 00

00 66 68 00 02 00 00 66  68 08 00 00 00 66 53 66

53 66 55 66 68 00 00 00  00 66 68 00 7C 00 00 66

61 68 00 00 07 CD 1A 5A  32 F6 EA 00 7C 00 00 CD

18 A0 B7 07 EB 08 A0 B6  07 EB 03 A0 B5 07 32 E4

05 00 07 8B F0 AC 3C 00  74 09 BB 07 00 B4 0E CD

10 EB F2 F4 EB FD 2B C9  E4 64 EB 00 24 02 E0 F8

24 02 C3 49 6E 76 61 6C  69 64 20 70 61 72 74 69

74 69 6F 6E 20 74 61 62  6C 65 00 45 72 72 6F 72

20 6C 6F 61 64 69 6E 67  20 6F 70 65 72 61 74 69

6E 67 20 73 79 73 74 65  6D 00 4D 69 73 73 69 6E

67 20 6F 70 65 72 61 74  69 6E 67 20 73 79 73 74

65 6D 00 00 00 63 7B 9A  15 F2 CA 2C 00 00 00 20

21 00 07 FE FF FF 00 08  00 00 00 00 80 0C 00 FE

FF FF 07 FE FF FF 00 08  80 0C 00 00 00 19 00 FE

FF FF 07 FE FF FF 00 08  80 25 00 00 80 25 00 FE

FF FF 0F FE FF FF 00 08  00 4B 00 F0 FF 2A 55 AA

2.3 读取硬盘MBR数据C++语言代码

#include "windows.h"   
#include "stdio.h"   
const UINT uSectorSize = 512;
const UINT uBegSector = 0;
const UINT uSectorNum = 1;
const UINT uReadSize = 512*1;
BYTE bBuffer[512] = { 0 };
const char pDiskPath[] =  "\\\\.\\PHYSICALDRIVE2";
void ShowByteInform(PBYTE pBuf, UINT uSize)
{
for (UINT i = 1; i <= uSize; i++)
{
printf("%02X ", pBuf[i - 1]);
if (i % 16 == 0)
{
printf("\n");
}
else if (i % 8 == 0)
{
printf(" ");
}
}
}
int main(int argc, char* argv[])
{
HANDLE hDisk;
HANDLE hFile;
hDisk = CreateFile(pDiskPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDisk == INVALID_HANDLE_VALUE)
{
MessageBox(0, "can't open the disk!", 0, 0);
return 0;
}
SetFilePointer(hDisk, uBegSector*uSectorSize, 0, FILE_BEGIN);
DWORD dwReadByte;
ReadFile(hDisk, (LPVOID)bBuffer, uReadSize, &dwReadByte, NULL);
if (dwReadByte == 0)
{
MessageBox(0, "read disk error!", 0, 0);
return 0;
}
ShowByteInform(bBuffer, uReadSize);
hFile =CreateFile("\\\\.\\D:\\MBR_BackUp.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //将数据保存到D盘MBR_BackUp.txt
if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(0, "can't open the file!", 0, 0);
return 0;
}
WriteFile(hFile, (LPVOID)bBuffer, uReadSize, &dwReadByte, NULL);
if (dwReadByte == 0)
{
MessageBox(0, "write file error!", 0, 0);
return 0;
}
CloseHandle(hFile);
CloseHandle(hDisk);
while (1);
return 0;
}

2-2 GUID Partition Table(GPT)分区

GPT头格式

偏移量

大小/字节

说明

0 (0x00)

8

标识“EFI PART”,45h 46h 49h 20h 50h 41h 52h 54h

8 (0x08)

4

保留(00h 00h 01h 00h)

12 (0x0C)

4

头大小/字节(5Ch 00h 00h 00h)

16 (0x10)

4

GPT 头的CRC32校验

20 (0x14)

4

保留,必须为0

24 (0x18)

8

当前逻辑扇区号

32 (0x20)

8

备份逻辑扇区号

40 (0x28)

8

First usable LBA for partitions (primary partition table last LBA + 1)

48 (0x30)

8

Last usable LBA (secondary partition table first LBA - 1)

56 (0x38)

16

Disk GUID (also referred as UUID on UNIXes)

72 (0x48)

8

分区表起始扇区号

80 (0x50)

4

Number of partition entries in array 队列中的分区数(最多128个分区)

84 (0x54)

4

单个分区表的大小(80H)

88 (0x58)

4

分区阵列的CRC32

92 (0x5C)

*

保留,420字节(512字节/每扇区)

3号扇区第2个分区表的起始扇区“0x040800”与用Winhex读取到的BPB参数中的隐藏扇区数一致,总扇区数=(最后扇区-起始扇区)+1。

Microsoft reserved patition:对于小于 16 GB 的磁盘,MSR 分区为 32 MB。对于大于 16 GB 的磁盘,MSR 分区为 128 MB。

3 ExFAT文件系统卷分布

偏移量/扇区

大小/扇区

说明

Main Boot Region 主引导区

0

1

Boot Sector

引导扇区

1

8

Extended Boot Sectors

扩展引导扇区

9

1

OEM Parameters

OEM参数

10

1

Reserved

保留区,数据全为0

11

1

Boot Checksum

引导校验和

Backup Boot Region备份引导区

12

1

Boot Sector

引导扇区

13

8

Extended Boot Sectors

扩展引导扇区

21

1

OEM Parameters

OEM参数

22

1

Reserved

保留区

23

1

Boot Checksum

引导校验和

FAT Region  FAT表区

FAT表起始扇区号

占1个簇的空间

FAT 表项

FAT表起始扇区号及FAT表扇区数见BPB参数

Data Region数据区

首簇起始扇区号(2号簇)

占1个簇的空间

簇位图文件

见BPB参数

3号簇:(3-2)*每簇扇区数+首簇起始扇区号

占1个簇的空间,数据占5836字节,剩余为保留区

大写字符文件


4号簇:(4-2)*每簇扇区数+首簇起始扇区号

占1个簇的空间

根目录文件项


3.1 Main Boot Region 主引导区

3.1.2 扩展引导扇区(Extended Boot Sector)

偏移量

大小

描述

说明

0x00

512-4=508

扩展引导码

如果不用则全为00

0x1FC

4

扩展引导结束标志

0x000055AA

在1-8号扇区

3.1.4 引导校验和(ExFAT Boot Checksum)

该扇区重复了32bit的对前11个扇区(0~10号扇区)数据的校验和,校验和的计算不包括引导扇区中的卷标志和使用百分比(第106、107、112字节)。校验和一直重复到该扇区结束。

校验和计算代码

UNIT32 BootChecksum(const unsigned chardata[], int bytes)
{
UINT32 checksum   =   0; 
for (inti = 0; i < bytes; i++)
{
if (i == 106 || i == 107 || i == 112)
continue;
checksum = (checksum<<31) | (checksum>> 1) + data[i];
}
returnchecksum;
}

Backup Boot Region备份引导区(12~23号扇区)与Main Boot Region 主引导区(0~11号扇区)数据完成一样。

4 FAT Region FAT表区

参数名称

参数值

参数名称

参数值

隐藏扇区数

0x0800

分区内的总簇数

Ox37E2

分区总扇区数

0x37E42000

根目录首簇号

0x04

FAT表起始扇区号

0x010000

每扇区字节数

2^9=512

FAT表扇区数

0x010000

每簇扇区数

2^16=65536

首簇起始扇区号

0x020000

FAT表个数

1

从BPB参数中可以得到FAT表的起始扇区号为0x010000 =65536。在Winhex跳转到65536号扇区可看到FAT表数据。

ExFAT的每个FAT项由4字节构成,也就是32位的表项。

每个FAT项都有一个固定的编号,这个编号从0开始,也就是说,第一个FAT项是0号FAT项,第二个FAT项是1号FAT项,以此类推。

每个FAT项占用4字节:其中0号FAT项描述介质类型,其首字节为“F8”,表示介质类型为硬盘;1号FAT项写入4个“FF”;从2号FAT项开始对应2号簇,3号FAT项开始对应3号簇,一直到最后一个簇。目前2、3、4三个FAT项中都是结束标志,说明簇位图文件、大写字符文件、根目录各占一个簇。

分区的数据区中的每一个簇都会映射到FAT表中的唯一一个FAT项。因为0号FAT项和1号FAT项有特殊的用途,无法与数据区中的簇形成映射,所以数据区中的第一个簇也就编号为2号簇,这也是没有0号簇和1号簇的原因,然后3号簇与3号FAT项映射,4号簇与4号FAT项映射,以此类推。

分区格式化后,分区的两个元文件(簇位图文件和大写字符文件)及用户文件都以簇为单位存放在数据区中,一个文件至少占用一个簇。当一个文件占用多个簇时,这些簇的簇号可能是连续的,也可能是不连续的。如果文件存放的簇不连续,这些簇的簇号就以簇链的形式登记在FAT表中;而如果文件存放在连续的簇中,FAT表则不登记这些连续的簇链。

⑧综合上面的说明可以看出,ExFAT文件系统FAT表的功能主要是登记不连续存储的文件的簇链,所以在FAT中可以看到数值为0的FAT项,并不能说明该FAT项对应的簇是可用簇。

占用不连续簇的文件,fat表记录

(1)1.txt文件占5、7号簇,2.txt占6号簇,fat表如下:

(2)1.txt文件占5、7号簇,2.txt占6号簇,3.txt文件占8、0x0A号簇,4.txt占9号簇,fat表如下:

(3)1.txt文件占5、7号簇,2.txt占6、0x0B、0x0C号簇,3.txt文件占8、0x0A号簇,4.txt占9号簇,fat表如下:

(4)1.txt文件占5、7号簇,2.txt占6、0x0B、0x0C、0x0D号簇,3.txt文件占8、0x0A号簇,4.txt占9号簇,fat表如下:

仅占一个簇,或占连续簇的文件,对应fat项均为00

(5)1.txt文件占5、7号簇,2.txt占6、0x0B、0x0C、0x0D号簇,3.txt文件占8、0x0A号簇,4.txt占9号簇,5.txt占0x0E、0x0F、0x10、0x11 ,6.txt占0x12、0x14,7.txt占0x13号簇fat表如下:

5 簇位图文件

数据区中的第一个簇就是2号簇,2号簇一般都分配给簇位图文件使用。

参数名称

参数值

参数名称

参数值

隐藏扇区数

0x0800

分区内的总簇数

Ox37E2

分区总扇区数

0x37E42000

根目录首簇号

0x04

FAT表起始扇区号

0x010000

每扇区字节数

2^9=512

FAT表扇区数

0x010000

每簇扇区数

2^16=65536

首簇起始扇区号

0x020000

FAT表个数

1

从BPB参数可以得到首簇起始扇区号0x020000 =131072,Winhex跳转到131072号扇区可看到簇位图。

该扇区只有一个字节“07H”,这就是簇位图文件的内容。

簇位图文件是ExFAT文件系统中的一个元文件,类似于NTFS文件系统中的元文件$BitMap,它的作用是用来管理分区中簇的使用情况。簇位图文件中的每一个位,映射到数据区中的每一个簇。如果某个簇分配给了文件,该簇在簇位图文件中对应的位就会被填入“1”,表示该簇已经占用;如果没有使用的空簇,它们在簇位图文件中对应的位就是“0”。

簇位图文件的内容为“07H”,换算成二进制等于“0000 0111”,这8位就对应数据区的8个簇,也就是从2号簇到9号簇这8个簇。从“0000 0111”这个数值中能够很明确的看出2、3、4这三个簇是被使用的,其它5个簇未被使用。而2、3、4这三个簇正是被簇位图文件、大写字符文件、根目录所占用的。

在簇位图文件的目录项中可以看到簇位图文件的起始簇号及文件的大小。

6 大写字符文件

大写字符文件是ExFAT文件系统中的第二个元文件,类似于NTFS文件系统中的元文件$UpCase。Unicode字母表中的每一个字符在这个文件中都有对应的条目,用于比较、排序、计算Hash值方面。

簇位图文件结束后的下一个簇一般分配给大写字符文件使用,也就是3号簇开始,扇区号:(3-2)*每簇扇区号+首簇起始扇区号 =65536+131072=196608号扇区。

参数名称

参数值

参数名称

参数值

隐藏扇区数

0x0800

分区内的总簇数

Ox37E2

分区总扇区数

0x37E42000

根目录首簇号

0x04

FAT表起始扇区号

0x010000

每扇区字节数

2^9=512

FAT表扇区数

0x010000

每簇扇区数

2^16=65536

首簇起始扇区号

0x020000

FAT表个数

1

大写字符文件第一个扇区的一部分,从图中可以看到其内容都是Unicode字母表中的字符,每一个字符占用两个字节。大写字符文件的大小固定为5836字节。

7 根目录文件项

目录项对于ExFAT文件系统来讲是非常重要的组成部分,其主要作用及结构特点如下:

①分区中的每个文件及文件夹(也称为目录)都被分配多个大小为32字节的目录项,用以描述文件及文件夹的属性、大小、起始簇号和时间、日期等信息,当然还会把文件名或目录名也记录在目录项中。

②在ExFAT文件系统中,目录也被视为特殊类型的文件,所以每个目录也与文件一样有目录项。

③在ExFAT文件系统下,分区根目录下的文件及文件夹的目录项存放在根目录区(4号簇)中,分区子目录下的文件及文件夹的目录项存放在数据区(从5号簇开始及后面的簇)相应的簇中。

④ExFAT文件系统目录项的第一个字节用来描述目录项的类型,剩下的31个字节用来记录文件的相关信息。

⑤根据目录项的作用和结构特点,可以把目录项分为四种类型:

◆卷标目录项;

◆簇位图文件的目录项;

◆大写字符文件的目录项;

◆用户文件的目录项。

根目录文件在第4号簇,起始扇区位置:(4-2)*每簇扇区号+首簇起始扇区号=2*65536+131072=262144,Winhex跳转到262144号扇区可以看到根目录文件。

7.1 卷标目录项

卷标就是一个分区的名称,可以在格式化分区时创建,也可以随时修改。ExFAT文件系统把卷标当做文件,用文件目录项进行管理。系统为卷标建一个目录项,放在根目录区中。

卷标的目录项占用32字节,其中第一个字节时特征值,用来描述类型。卷标目录项的特征值为“83H”,如果没有卷标或者将卷标删除,该特征值为“03H”。

卷标的长度理论上为11个字符。

卷标为“ExFAT sys”

卷标目录项中各字节的含义见表7-1。

(表7-1 ExFAT卷标目录项的含义)

字节偏移

字段长度(字节)

内容及含义

0x00

1

目录项的类型(特征值为“83H”)

0x01

1

卷标字符数

0x02

22

卷标

0x18

8

保留

卷标目录项有如下特点:

①对于ExFAT格式的分区,卷标的字符要求在11个之内。卷标使用unicode码字符。

②卷标的目录项中不记录起始簇号和大小。

③卷标的目录项中不记录时间戳。

7.2 簇位图文件的目录项

ExFAT文件系统格式化时会创建一个簇位图文件,并为其建一个目录项,放在根目录区中。

簇位图文件的目录项占用32个字节,其中第一个字节是特征值,用来描述类型。簇位图文件目录项的特征值为“81H”。

簇位图文件目录项中各字节的含义见表7--2。

(表7--2 ExFAT簇位图文件目录项的含义)

字节偏移

字段长度(字节)

内容及含义

0x00

1

目录项的类型(特征值为“81H”)

0x01

1

保留

0x02

18

保留

0x14

4

起始簇号

0x18

8

文件大小

簇位图文件的目录项有如下特点:

①对于ExFAT格式的分区,簇位图文件起始簇号一般为2。

②簇位图文件的目录项中不记录时间戳。

7.3 大写字符文件的目录项

ExFAT文件系统格式化时会创建一个大写字符文件,并为其建一个目录项,放在根目录区中。

大写字符文件的目录项占用32个字节,其中第一个字节是特征值,用来描述类型。大写字符文件目录项的特征值为“82H”。

大写字符文件目录项中各字节的含义见表7--3。

(表7--3 ExFAT大写字符文件目录项的含义)

字节偏移

字段长度(字节)

内容及含义

0x00

1

目录项的类型(特征值为“82H”)

0x01

3

保留

0x04

4

校验和

0x08

12

保留

0x14

4

起始簇号

0x18

8

文件大小

大写字符文件的目录项有如下特点:

①对于ExFAT格式的分区,大写字符文件的目录项一般都跟在簇位图文件的目录项之后。

②大写字符文件的目录项中不记录时间戳。

7.4 用户文件的目录项

ExFAT文件系统中每个用户文件至少有三个目录项,这三个目录项被称为三个属性:第一个目录项称为“属性1”,目录项首字节的特征值为“85H”;第二个目录项称为“属性2”,目录项首字节的特征值为“C0H”;第三个目录项称为“属性3”,目录项首字节的特征值为“C1H”。

7.4.2 属性2目录项

“属性2”目录项用来记录文件是否有碎片、文件名的字符数、文件名的Hash值、文件的起始簇号及大小等信息。

用户文件的“属性2”目录项中各字节的含义见表7--6。

(表7--6 用户文件的“属性2”目录项的含义)

字节偏移

长度/字节

内容及含义

0x00

1

目录项的类型(特征值为“C0H”)

0x01

1

文件碎片标志。如果是连续存放没有碎片,该标志为“03H”;如果是不连续存放,文件有碎片,该标志就为“01H”

0x02

1

保留

0x03

1

文件名字符数N。用unicode码表示,每个字符占用2个字节

0x04

2

文件名Hash值。当文件名发生改变时,Hash值也会发生改变。

0x06

2

保留

0x08

8

文件大小1。文件的总字节数

0x10

4

保留

0x14

4

起始簇号

0x18

8

文件大小2。一般情况下与“文件大小1”的数值保持一致

Hash值的计算

u16  NameHash(u8 *fileName, u8 nameLength)
{
u16 hash = 0,cc;
int i;
for (i = 0; i <nameLength; i++)
{
cc = char_upcase(*fileName++);
hash = (u16)(((hash << 15) | (hash >> 1)) + (cc & 0x00ff));
hash = (u16)(((hash << 15) | (hash >> 1)) + ((cc & 0xff00) >> 8));
}
return hash;
}

7.4.3 属性3目录项

“属性3”目录项用来具体记录文件的名称。如果文件名很长,“属性3”可以包含多个目录项,每个目录项称为一个片段,从上至下依次记录文件名的每一个字符。

文件名:“helloExfat.txt”

文件名:“0123456789abcdefghijklmnopqrstuvwxyz.txt”

用户文件的“属性3”目录项中各字节的含义见表7--7。

(表7--7 用户文件的“属性3”目录项的含义)

字节偏移

字段长度(字节)

内容及含义

0x00

1

目录项的类型(特征值为“C1H”)

0x01

1

保留

0x02

2N

文件名

例如在根目录项创建一个名为文件“helloExfat.txt”的文件,文件中的内容为:“0123456789abcdefghijklmnopqrstuvwxyz”,根目录文件项的数据如图所示。

文件创建时间:0x4AEA7042

最后修改时间和最后访问时间:0x4AEA709D

文件碎片标志:0x03,没有碎片

文件名长度:0x0E,14字节

文件大小:0x24,36字节

起始簇号:05 ,跳转到5号簇可看到文件中的内容。扇区号:(5-2)*65536+131072=327680

长文件名,C1续

8 ExFAT文件系统的根目录及子目录的管理

在根目录下创建一个文件夹“001”和一个文件“root01.txt”如下图所示

在“001”文件夹下再创建一个“002”文件夹和一个“00101.txt”文件

进入5号簇查看文件夹“001”中的内容

进入8号簇查看“001/00101”文件夹的内容

进入9号簇,查看“001/00101”文件夹下“0010101.txt”文件内容:

从以上可以看出文件夹的文件大小均为“0x02 00 00 00” = 32M ,为一个簇的大小。

此时的簇位图信息:

5~9号簇均被占用了。

文件创建总结:

创建文件目录项

向对应的簇号中写入shuj

将簇位图中相应的簇号置“1”

9 删除文件

根目录下的文件“root01.txt”,文件中内容为“this file is in root folder”,删除前文件目录项如下图所示。

将“root01.txt”文件删除后,文件目录项为:

进入到6号簇,查看:

发现数据并没有被清空。

10 Exfat文件系统元文件大小分配问题

簇位图大小=(卷大小-首簇扇区号)/每簇扇区数

Fat表大小=卷大小/每簇大小*4

FAT表初始化

在Windows下目录项的插入规则:

在目录项的最后一个簇中,以32字节为单位,查找首字节为“00”的位置添加目录项信息;

如果目录项文件的最后一个簇末尾剩余空间不足以存放一个新的完整的目录项信息,则该簇里面查找是否有删除文件“05H 40H 41H”,如果有,则覆盖;

如果以上两步都没有找到合适的位置,则找到下一个可用簇。如果上一个簇中有部分空余的空间,但不够,则将目录项信息填满空余空间后,将剩余的信息存到下一个簇中,前后两个簇的首尾连续起来。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多