第 3 章 - Azure RTOS FileX 功能组件

本章旨在从功能角度介绍高性能 Azure RTOS FileX 嵌入式文件系统。

介质说明

FileX 是符合 FAT 文件系统格式的高性能嵌入式文件系统。 FileX 将物理介质视为逻辑扇区数组。 如何将这些扇区与底层物理介质相映射取决于 fx_media_open 调用期间连接到 FileX 介质的 I/O 驱动程序。

FAT12/16/32 逻辑扇区

介质逻辑扇区的确切组织取决于物理介质启动记录的内容。 介质逻辑扇区的一般布局如图 1 所示。

FileX 逻辑扇区始于逻辑扇区 1,指向介质的第一个保留扇区。 虽然保留扇区为可选,但在使用时,这些扇区通常包含启动代码等系统信息。

FAT12/16/32 介质启动记录

介质“逻辑扇区”视图中其他区域的确切扇区偏移来自介质启动记录的内容。 启动记录通常位于第 0 扇区。 但是,如果介质具有隐藏扇区,则启动扇区的偏移必须考虑到这些隐藏扇区(位于启动扇区之前)。 表 1 列出了介质的启动记录组件,这些组件将在下文段落中进行介绍。

  • 跳转指令“跳转指令”字段是一个三字节字段,表示处理器跳转的 Intel x86 机器指令。 在大多数情况下,“跳转指令”属于遗留字段。

    FileX 介质逻辑扇区视图

    图 1。 FileX 介质逻辑扇区视图

  • OEM 名称“OEM 名称”字段保留供制造商放置他们的名称或设备名称。

  • 每扇区字节数介质启动记录中的“每扇区字节数”字段定义每个扇区(介质的基本元素)的字节数。

  • 每群集扇区数介质启动记录中的“每群集扇区数”字段定义分配给每个群集的扇区数。 群集是 FAT 兼容文件系统中的基础分配元素。 所有文件信息和子目录都是根据文件分配表 (FAT),从介质的可用群集中进行分配。

    表 1。 FileX 介质启动记录

    Offset 字段 字节数
    0x00 跳转指令(e9、xx、xx 或 eb、xx、90) 3
    0x03 OEM 名称 8
    0x0B 每扇区字节数 2
    0x0D 每群集扇区数 1
    0x0E 保留扇区数 2
    0x10 FAT 数 1
    0x11 根目录大小 2
    0x13 扇区数目 FAT-12 & FAT-16 2
    0x15 介质类型 1
    0x16 每 FAT 扇区数 2
    0x18 每磁道扇区数 2
    0x1A 磁头数 2
    0x1C 隐藏扇区数 4
    0x20 扇区数 - FAT-32 4
    0x24 每 FAT (FAT-32) 扇区数 4
    0x2C 根目录群集 4
    0x3E 系统启动代码 448
    0x1FE 0x55AA 2
  • 保留扇区数介质启动记录中的“保留扇区数”字段定义在启动记录和 FAT 区域第一个扇区之间保留的扇区数。 在大多数情况下,此条目为零。

  • FAT 数介质启动记录中的“FAT 数”条目定义介质中的 FAT 数。 介质中必须始终至少有一个 FAT。 其他 FAT 只是主要(第一个)FAT 的副本,通常由诊断或恢复软件使用。

  • 根目录大小介质启动记录中的“根目录大小”条目定义介质根目录中的固定条目数。 此字段不适用于子目录和 FAT-32 根目录,因为它们从介质的群集中分配而来。

  • FAT-12 和 FAT-16 扇区数介质启动记录中的“扇区数”字段包含介质中的扇区总数。 如果此字段为零,则扇区总数将包含在位于启动记录之后的“FAT-32 扇区数”字段中。

  • 介质类型“介质类型”字段用于标识设备驱动程序中的介质类型。 这属于遗留字段。

  • 每 FAT 扇区数介质启动记录中的“每 FAT 扇区数”字段包含与 FAT 区域中每个 FAT 关联的扇区数。 FAT 扇区数必须足够大,以满足介质中可以分配的最大群集数。

  • 每磁道扇区数介质启动记录中的“每磁道扇区数”字段定义每个磁道的扇区数。这通常仅适用于实际磁盘型介质。 闪存设备不使用此映射。

  • 磁头数介质启动记录中的“磁头数”字段定义介质中的磁头数。 这通常仅适用于实际磁盘型介质。 闪存设备不使用此映射。

  • 隐藏扇区数介质启动记录中的“隐藏扇区数”字段定义启动记录之前的扇区数。 此字段在 FX_MEDIA 控制块中进行维护,并且必须在 FileX 发出的所有读取和写入请求的 FileX I/O 驱动程序中进行说明。

  • FAT-32 扇区数仅当双字节“扇区数”字段为零时,介质启动记录中的“扇区数”字段才有效。 在这种情况下,此四字节字段包含介质中的扇区数。

  • 每 FAT (FAT-32) 扇区数“每 FAT (FAT-32) 扇区数”字段仅适用于 FAT-32 格式,并包含为介质的每个 FAT 分配的扇区数。

  • 根目录群集“根目录群集”字段仅适用于 FAT-32 格式,并包含根目录的起始群集号。

  • 系统启动代码“系统启动代码”字段是用于存储一小部分启动代码的区域。 目前在大多数设备中,“系统启动代码”属于遗留字段。

  • 签名 0x55AA“签名”字段是用于标识启动记录的数据模式。 如果此字段不存在,则启动记录无效。

exFAT

FAT32 中的最大文件大小为 4GB,这限制了高清晰多媒体文件的广泛采用。 默认情况下,FAT32 支持最大为 32GB 的存储介质。 随着闪存和 SD 卡容量的增加,FAT32 在管理大容量文件时效率较低。 exFAT 旨在克服这些限制。 exFAT 支持的文件大小可高达 1 艾字节 (EB),约为 10 亿 GB。 ExFAT 和 FAT32 的另一个重要区别在于,exFAT 使用位图来管理卷中的可用空间,使得其在向文件中写入数据时能够更有效地查找可用空间。 对于存储在连续群集中的文件,exFAT 无需遍历 FAT 链以查找所有群集,从而在访问大型文件时更有效。 闪存存储和 SD 卡大于 32GB 时,需要使用 exFAT。

exFAT 逻辑扇区

exFAT 中介质逻辑扇区的一般布局如图 2 所示。 在 exFAT 中,启动块和 FAT 区域属于系统区域。 其余群集属于用户区域。 虽然没有严格限制,但 exFAT 标准确实建议“分配位图”位于“用户区域”的起始位置,其次是“大写转换表”和根目录。

exFAT 介质启动记录

ExFAT 与 FAT12/16/32 拥有不同的“介质启动记录”内容。 ExFAT 介质启动记录内容如表 2 所示。 为避免混淆,0x0B 和 0x40 之间的区域(其中包含 FAT12/16/32 中的各种介质参数)在 exFAT 中标记为“保留”。 此保留区域必须设置为零,以避免任何对“介质启动记录”的误解。

exFAT 逻辑扇区

图 2。 exFAT 逻辑扇区

  • 跳转指令“跳转指令”字段是一个三字节字段,表示处理器跳转的 Intel x86 机器指令。 在大多数情况下,“跳转指令”属于遗留字段。

    表 2。 exFAT 介质启动记录

    Offset 字段 字节数
    0x00 跳转指令 3
    0x03 文件系统名称 8
    0x0B 保留 53
    0x40 分区偏移 8
    0x48 卷长度 8
    0x50 FAT 偏移 4
    0x54 FAT 长度 4
    0x58 群集堆偏移 4
    0x5C 群集计数 4
    0x60 根目录的第一个群集 4
    0x64 卷序列号 4
    0x68 文件系统修订 2
    0x6A 卷标志 2
    0x6C 每扇区字节数移位 1
    0x6D 每群集扇区数移位 1
    0x6E FAT 数 1
    0x6F 驱动器选择 1
    0x70 使用百分比 7
    0x71 保留 1
    0x78 启动代码 390
    0x1FE 启动签名 2
  • 文件系统名称 对于 exFAT,“文件系统名称”字段必须是“exFAT”,后跟三个尾随空格。

  • 保留“保留”字段的内容必须为零。 此区域与 FAT12/16/32 中的启动记录重叠。 将此区域设置为零可避免文件系统对该卷的错误解释。

  • 分区偏移“分区偏移”字段表示此分区的起始位置。

  • 卷长度“卷长度”字段定义此分区的大小,以扇区数表示。

  • FAT 偏移“FAT 偏移”字段定义此分区 FAT 表的起始扇区号(相对于此分区的起始位置)。

  • FAT 长度“FAT 长度”字段定义 FAT 表的大小,以扇区数表示。

  • 群集堆偏移“群集堆偏移”字段定义群集堆的起始扇区号(相对于此分区的起始位置)。 群集堆是存储目录信息和文件数据的区域。

  • 群集计数“群集计数”字段定义此分区的群集数。

  • 根目录的第一个群集“根目录的第一个群集”字段定义根目录的起始位置,建议位于分配位图和大写转换表之后。

  • 卷序列号“卷序列号”字段定义此分区的序列号。

  • 文件系统修订“文件系统修订”字段定义 exFAT 的主版本和次版本。

  • 卷标志“卷标志”字段包含指示此卷状态的标志。

  • 每扇区字节数移位“每扇区字节数移位”字段定义每个扇区的字节数,以 log2(n) 表示,其中 n 为每个扇区的字节数。 例如,在 SD 卡中,扇区大小为 512 字节。 因此,此字段应为 9 (log2(512) = 9)。

  • 每群集扇区数移位“每群集扇区数移位”字段定义每个群集的扇区数,以 log2(n) 表示,其中 n 为每个群集的扇区数。

  • FAT 数“FAT 数”字段定义此分区中 FAT 表的数量。 对于 exFAT,建议此值为 1,即一个 FAT 表。

  • 驱动器选择“驱动器选择”字段定义扩展的 INT 13h 驱动器号。

  • 使用百分比“使用百分比”字段定义群集堆中正在分配的群集的百分比。 有效值介于 0 和 100(含)之间。

  • 保留此字段保留供将来使用。

  • 启动代码“启动代码”字段是用于存储一小部分启动代码的区域。 目前在大多数设备中,“系统启动代码”属于遗留字段。

  • 签名 0x55AA“启动签名”字段是用于标识启动记录的数据模式。 如果此字段不存在,则启动记录无效。

文件分配表 (FAT)

“文件分配表 (FAT)”在介质中的保留扇区之后启动。 FAT 区域本质上是由 12 位、16 位或 32 位条目组成的数组,用于确定该群集是分配而来,还是属于构成子目录或文件的群集链。 每个 FAT 条目的大小取决于需要表示的群集数。 如果群集数(由扇区总数除以每群集扇区数得出)小于或等于 4,086,则使用 12 位 FAT 条目。 如果群集总数大于 4,086 但小于 65,525,则使用 16 位 FAT 条目。 否则,如果群集总数大于或等于 65,525,则使用 32 位 FAT 或 exFAT。

对于 FAT12/16/32,FAT 表不仅维护群集链,还提供有关群集分配的信息,即群集是否可用。 在 exFAT 中,群集分配信息由“分配位图目录条目”进行维护。 每个分区都有其自己的分配位图。 位图的大小足以容纳所有可用的群集。 如果某个群集可用于分配,则分配位图中的对应位将设置为 0。 否则,该对应位将设置为 1。 对于占用连续群集的文件,exFAT 无需使用 FAT 链跟踪所有群集。 但是,对于不占用连续群集的文件,仍需要维护 FAT 链。

FAT 条目内容

FAT 表中的前两个条目并不使用,通常包含以下内容。

FAT 条目 12 位 FAT 16 位 FAT 32 位 FAT exFAT
条目 0 0x0F0 0x00F0 0x000000F0 0xF8FFFFFF
条目 1 0xFFF 0xFFFF 0x0FFFFFFF 0xFFFFFFFF

FAT 条目编号 2 表示介质数据区域中的第一个群集。 每个群集条目的内容可决定该群集是可用,还是属于分配给文件或子目录的群集链接列表。 如果群集条目包含另一个有效的群集条目,则将分配该群集,且其值指向群集链中分配的下一个群集。

可能的群集条目定义如下。

含义 12 位 FAT 16 位 FAT 32 位 FAT exFAT
可用群集 0x000 0x0000 0x00000000 0x00000000
不使用 0x001 0x0001 0x00000001 0x00000001
保留 0xFF0-FF6 0xFFF0-FFF6 0x0FFFFFF0-6 ClusterCounter + 2 至 0xFFFFFFF6
不良群集 0xFF7 0xFFF7 0x0FFFFFF7 0xFFFFFFF7
保留 - - - 0xFFFFFFF8-E
最后一个群集 0xFF8-FFF 0xFFF8-FFFF 0x0FFFFFF8-F 0xFFFFFFFF
群集链接 0x002-0xFEF 0x0002-FFEF 0x2-0x0FFFFFEF 0x2 - ClusterCount + 1

已分配的群集链中的最后一个群集包含“最后一个群集”值(如上定义)。 在文件或子目录的目录条目中找到第一个群集号。

内部逻辑缓存

FileX 为每个打开的介质维护最新使用的逻辑扇区缓存。 逻辑扇区缓存的最大大小由常量 FX_MAX_SECTOR_CACHE 定义,并位于 fx_api.h 中。 这是决定内部逻辑扇区缓存大小的第一个因素。

决定逻辑扇区缓存大小的另一个因素是由应用程序提供给 fx_media_open 调用的内存量。 需要有足够的内存,供至少一个逻辑扇区使用。 如果需要 FX_MAX_SECTOR_CACHE 个以上逻辑扇区,则必须在 fx_api.h 中更改常量,并且必须重新生成整个 FileX 库。

重要

FileX 中每个打开的介质可能具有不同的缓存大小,具体取决于打开调用期间提供的内存。

写入保护

借助 FileX,应用程序驱动程序能够在介质上动态设置写入保护。 如果需要写入保护,则驱动程序会将关联的 FX_MEDIA 结构中的 fx_media_driver_write_protect 字段设置为 FX_TRUE。 当如是设置后,则应用程序修改介质以及打开文件进行写入的所有尝试均会遭到拒绝。 驱动程序还可以通过清除此字段来禁用写入保护。

可用扇区更新

FileX 提供一种机制,用于在扇区不再使用时通知应用程序驱动程序。 这对于管理 FileX 使用的所有逻辑扇区的闪存管理器特别有用。

如果需要可用扇区通知,则应用程序驱动程序会将关联的 FX_MEDIA 结构中的 fx_media_driver_free_sector_update 字段设置为 FX_TRUE。 此分配通常在驱动程序初始化期间完成。

设置此字段后,FileX 会发出 FX_DRIVER_RELEASE_SECTORS 驱动程序调用,指示一个或多个连续扇区何时可用。

介质控制块 FX_MEDIA

介质控制块中包含 FileX 中每个打开的介质的特征。 fx_api.h 文件中定义了此结构。

介质控制块可以位于内存中的任意位置,但最常见的做法是在任何函数的作用域外部定义控制块,以使其成为全局结构。

如同所有动态分配内存一样,将控制块放置于其他区域时需要多加小心。 如果在 C 函数内分配控制块,则与之相关联的内存是调用线程堆栈的一部分。

警告

通常,请避免对控制块使用本地存储,因为在函数返回后,将释放其所有局部变量堆栈空间,而不管该空间是否仍在使用!

FAT12/16/32 目录说明

FileX 支持 8.3 和 Windows 长文件名 (LFN) 名称格式。 除了名称之外,每个目录条目还包含条目的属性、上次修改时间和日期、起始群集索引和条目大小(以字节为单位)。 FileX 8.3 目录条目的内容和大小如表 3 所示。

  • 目录名称

    FileX 支持长度为 1 到 255 个字符的文件名。 介质上单个目录条目中文件名为标准八个字符。 这些文件名在“目录名称”字段中保持左对齐,并以空白填充。 此外,包含名称的 ASCII 字符始终大写。

    “长文件名”(LFN) 由连续的目录条目以相反顺序表示,后跟 8.3 标准文件名。 创建的 8.3 名称包含与该名称关联的所有有意义的目录信息。 用于存放“长文件名”信息的目录条目的内容如表 4 所示,表 5 则显示了一个 39 字符 LFN 的示例,该 LFN 总共需要四个目录条目。

重要

fx_api.h 中定义的常量 FX_MAX_LONG_NAME_LEN 包含 FileX 支持的最大长度。

  • 目录文件扩展名

    对于标准 8.3 文件名,FileX 还支持可选的三字符目录文件扩展名。 如同八个字符的文件名一样,文件扩展名在“目录文件扩展名”字段中保持左对齐,以空白填充,并且始终大写。

    表 3。 FileX 8.3 目录条目

    Offset 字段 字节数
    0x00 目录条目名称 8
    0x08 目录扩展 3
    0x0B 属性 1
    0x0C NT(由长文件名格式引入,并为 NT 保留 [始终为 0]) 1
    0x0D 以毫秒为单位的创建时间(由长文件名格式引入,表示创建文件时的毫秒数。) 1
    0x0E 创建时间(以小时 & 分钟为单位 (由长文件名格式引入)表示创建文件的小时和分钟 ) 2
    0x10 创建日期(由长文件名格式引入,表示创建文件的日期。) 2
    0x12 上次访问日期(由长文件名格式引入,表示上次访问文件的日期。) 2
    0x14 起始群集(仅限高 16 位 FAT-32) 2
    0x16 修改时间 2
    0x18 修改日期 2
    0x1A 起始群集(低 16 位 FAT-32 或 FAT-12 或 FAT-16) 2
    0x1C 文件大小 4
  • 目录属性

    单字节“目录属性”字段条目包含一系列位,用于指定目录条目的各种属性。 目录属性定义如下:

    属性位 含义
    0x01 此为只读条目。
    0x02 此为隐藏条目。
    0x04 此为系统条目。
    0x08 此为卷标签条目
    0x10 此为目录条目。
    0x20 此条目已修改。

    由于所有属性位均互斥,因此一次可能会设置多个属性位。

  • 目录时间

    双字节“目录时间”字段包含对指定目录条目最后一次更改的小时、分钟和秒。 第 15 位到第 11 位为小时,第 10 位到第 5 位为分钟,而第 4 位到第 0 位则为秒数的一半。 实际秒数需除以 2 才能写入此字段。

  • 目录日期

    双字节“目录日期”字段包含对指定目录条目最后一次更改的年份(相对于 1980 年的偏移)、月份和日期。 第 15 位到第 9 位为年份偏移,第 8 位到第 5 位为月份偏移,而第 4 位到第 0 位为日期。

  • 目录起始群集

    对于 FAT-12 和 FAT-16,此字段占用 2 个字节。 对于 FAT-32,此字段占用 4 个字节。 此字段包含分配给条目(子目录或文件)的第一个群集号。

    注意

    *请注意,FileX 创建新文件时没有初始群集(“起始群集”字段为零),以便用户有选择地为新创建的文件分配连续数量的群集。 *

  • 目录文件大小

    四字节“目录文件大小”字段包含文件中的字节数。 如果该条目确实为子目录,则该“大小”字段为零。

长文件名目录

  • 序号

    单字节“序号”字段指定 LFN 条目编号。 由于 LFN 条目以相反顺序放置,因此,由单个 LFN 组成的 LFN 目录条目的序号值会减 1。 此外,8.3 文件名之前的 LFN 序号值必须为 1。

    表 4。 长文件名目录条目

    Offset 字段 字节数
    0x00 序号字段 1
    0x01 Unicode 字符 1 2
    0x03 Unicode 字符 2 2
    0x05 Unicode 字符 3 2
    0x07 Unicode 字符 4 2
    0x09 Unicode 字符 5 2
    0x0B LFN 属性 1
    0x0C LFN 类型(保留,始终为 0) 1
    0x0D LFN 校验和 1
    0x0E Unicode 字符 6 2
    0x10 Unicode 字符 7 2
    0x12 Unicode 字符 8 2
    0x14 Unicode 字符 9 2
    0x16 Unicode 字符 10 2
    0x18 Unicode 字符 11 2
    0x1A LFN 群集(未使用,始终为 0) 2
    0x1C Unicode 字符 12 2
    0x1E Unicode 字符 13 2
  • Unicode 字符

    双字节“Unicode 字符”字段旨在支持多种不同语言的字符。 标准 ASCII 字符的表达方式为存储在 Unicode 字符的第一个字节中的 ASCII 字符后跟一个空格字符。

  • LFN 属性

    单字节“LFN 属性”字段包含的属性将目录条目标识为 LFN 目录条目。 这可通过设置“只读”、“系统”、“隐藏”和“卷”属性来实现。

  • LFN 类型

    单字节“LFN 类型”字段是保留字段,始终为 0。

  • LFN 校验和

    单字节“LFN 校验和”字段表示关联的 MSDOS 8.3 文件名的 11 个字符的校验和。 此校验和存储在每个 LFN 条目中,以帮助确保 LFN 条目与适当的的 8.3 文件名相对应。

  • LFN 群集

    双字节“LFN 群集”字段未使用,始终为 0。

    表 5。 由 39 个字符 LFN 组成的目录条目

    条目 含义
    1 LFN 目录条目 3
    2 LFN 目录条目 2
    3 LFN 目录条目 1
    4 8.3 目录条目 (ttttt~n.xx)

exFAT 目录说明

exFAT 文件系统以不同的方式存储目录条目和文件名。 目录条目包含条目的属性以及创建、修改和访问条目时的各种时间戳。 其他信息(如文件大小和起始群集)存储在紧随主目录条目之后的“流扩展目录条目”中。 exFAT 仅支持“长文件名”(LFN) 名称格式。 exFAT 存储在紧随“流扩展目录条目”之后的“文件名目录条目”中,如表 2 所示。

exFAT 文件目录条目

关于 exFAT 文件目录条目及其内容的说明,见下表和后文段落。

  • 条目类型

    “条目类型”字段表示此条目的类型。 对于“文件目录条目”,此字段必须为 0x85。

  • 辅助条目计数

    “辅助条目计数”字段表示紧随主要条目之后的辅助条目数。 与文件目录条目关联的辅助条目包括一个流扩展目录条目和一个或多个文件名目录条目。

    表 6。 exFAT 文件目录条目

    Offset 字段 字节数
    0x00 条目类型 1
    0x01 辅助条目 1
    0x02 校验和 2
    0x04 文件属性 2
    0x06 保留 1 2
    0x08 创建时间戳 4
    0x0C 上次修改时间戳 4
    0x10 上次访问时间戳 4
    0x14 创建 10ms 增量 1
    0x15 上次修改 10ms 增量 1
    0x16 创建 UTC 偏移 1
    0x17 上次修改 UTC 偏移 1
    0x18 上次访问 UTC 偏移 1
    0x19 保留 2 7
  • 校验和

    “校验和”字段包含目录条目集中所有条目(文件目录条目及其辅助条目)的校验和值。

  • 文件属性

    单字节“属性”字段条目包含一系列位,用于指定目录条目的各种属性。 大多数属性位的定义与 FAT 12/16/32 相同。 目录属性定义如下:

    属性位 含义
    0x01 此为只读条目
    0x02 此为隐藏条目
    0x04 此为系统条目
    0x08 此为保留条目
    0x10 此为目录条目
    0x20 此条目已修改
    所有其他位 保留
  • Reserved1

    此字段应为零。

  • 创建时间戳

    “创建时间戳”字段,结合“创建 10ms 增量”字段中的信息,描述创建文件或目录的本地日期和时间。

  • 上次修改时间戳

    “上次修改时间戳”字段,结合“上次修改 10ms 增量”字段中的信息,描述上次修改文件或目录的本地日期和时间。 请参阅下文时间戳注意事项。

  • 上次访问时间戳

    “上次访问时间戳”字段描述上次访问文件或目录的本地日期和时间。 请参阅下文时间戳注意事项。

  • 创建 10ms 增量

    “创建 10ms 增量”字段,结合“创建时间戳”字段中的信息,描述创建文件或目录的本地日期和时间。 请参阅下文时间戳注意事项。

  • 上次修改 10ms 增量

    “上次修改 10ms 增量”字段,结合“上次修改时间戳”字段中的信息,描述上次修改文件或目录的本地日期和时间。 请参阅下文时间戳注意事项。

  • 创建 UTC 偏移

    “创建 UTC 偏移”字段描述创建文件或目录时本地时间和 UTC 时间之间的差异。 请参阅下文时间戳注意事项。

  • 上次修改 UTC 偏移

    “上次修改 UTC 偏移”字段描述上次修改文件或目录时本地时间和 UTC 时间之间的差异。 请参阅下文时间戳注意事项。

  • 上次访问 UTC 偏移

    “上次访问 UTC 偏移”字段描述上次访问文件或目录时本地时间和 UTC 时间之间的差异。 请参阅下文时间戳注意事项。

  • Reserved2

    此字段应为零。

时间戳注意事项

  • 时间戳条目“时间戳”字段解释如下:

  • 10ms 增量字段“10ms 增量”字段中的值为时间戳值提供了更精细的粒度。 有效值介于 0 (0ms) 和 199 (1990ms) 之间。

    10ms 增量字段

  • UTC 偏移字段

    UTC 偏移字段

  • 偏移值

    7 位带符号整数表示相对于 UTC 时间的偏移(以 15 分钟为增量)。

  • 有效

    表示“偏移值”字段中的值是否有效。 0 表示“偏移值”字段中的值无效。 1 表示“偏移值”字段中的值有效。

流扩展目录条目

关于“流扩展目录条目”及其内容的说明如下表所示。

表 7。 流扩展目录条目

Offset 字段 字节数
0x00 条目类型 1
0x01 Flags 1
0x02 保留 1 1
0x03 名称长度 1
0x04 名称哈希 2
0x06 保留 2 2
0x08 有效数据长度 8
0x10 保留 3 4
0x14 第一个群集 4
0x18 数据长度 8
  • 条目类型

    “条目类型”字段表示此条目的类型。 对于流式处理扩展目录条目,此字段必须为 0xC0。

  • 标记

    此字段包含一系列指定各种属性的位:

    标记位 含义
    0x01 此字段表示是否可以分配群集。 此字段应为 1。
    0x02 此字段表示关联的群集是否连续。 值 0 表示 FAT 条目有效,FileX 应遵循 FAT 链。 值 1 表示 FAT 条目无效,群集具有连续性。
    所有其他位 保留。
  • 保留 1

    此字段应为 0。

  • 名称长度

    “名称长度”字段包含文件名目录条目中共同包含的 Unicode 字符串的长度。 文件名目录条目应紧跟在此流扩展目录条目之后。

  • 名称哈希

    “名称哈希”字段是双字节条目,包含大写文件名的哈希值。 利用哈希值,可更快地查找文件/目录名称:如果哈希值不匹配,则与此条目关联的文件名亦不匹配。

  • 保留 2

    此字段应为 0。

  • 有效数据长度

    “有效数据长度”字段表示文件中的有效数据量。

  • 保留 3

    此字段应为 0。

  • 第一个群集

    “第一个群集”字段包含数据流的第一个群集的索引。

  • 数据长度

    “数据长度”字段包含已分配群集中的字节总数。 此值可能大于“有效数据长度”,因为 exFAT 允许预分配数据群集。

根目录

在 FAT 12 位和 16 位格式中,根目录位于介质中所有 FAT 扇区之后,可以通过检查打开的 FX_MEDIA 控制块中的 fx_media_root_sector_start 进行查找。 根目录的大小以目录条目数(每 32 个字节的大小)表示,取决于介质启动记录中的相应条目。

FAT-32 和 exFAT 中的根目录可位于可用群集中的任意位置。 其位置和大小取决于打开介质时的启动记录。 打开介质后,可以使用 fx_media_root_sector_start 字段查找 FAT-32 或 exFAT 根目录的起始群集。

子目录

FAT 系统中有任意数量的子目录。 子目录的名称与文件名一样位于目录条目中。 但是,目录属性规范 (0x10) 设置为表示该条目为子目录,且文件大小始终为零。 全新单群集子目录(带有一个名为 FILE.TXT 文件的 SAMPLE.DIR)的典型子目录结构如图 3 所示。 在大多数情况下,子目录与文件条目非常相似。 “第一个群集”字段指向群集链接列表的第一个群集。 创建子目录时,前两个目录条目包含默认目录,即 "." 目录和 ".." 目录。 "." 目录指向子目录本身,而 ".." 目录指向上一个或父目录。

全局默认路径

FileX 为介质提供全局默认路径。 默认路径用于任何未明确指定完整路径的文件或目录服务。

最初,全局默认目录设置为介质的根目录。 应用程序可以通过调用 fx_directory_default_set 对全局默认目录进行更改。

可以通过调用 fx_directory_default_get 来检查介质的当前默认路径。 此例程提供一个字符串指针,该指针指向在 FX_MEDIA 控制块内进行维护的默认路径字符串。

本地默认路径

FileX 还提供了针对线程的默认路径,该路径允许不同的线程具有唯一路径,而不会发生冲突。 应用程序在调用 fx_directory_local_path_set 和 fx_directory_local_path_restore 期间提供 FX_LOCAL_PATH 结构,用于修改调用线程的本地路径。

如果存在本地路径,则本地路径优先于全局默认介质路径。 如果未设置本地路径,或者使用 fx_directory_local_path_clear 服务清除了本地路径,则会再次使用介质的全局默认路径。

文件描述

FileX 支持标准 8.3 字符和带有三个字符扩展名的长文件名。 除了 ASCII 名称之外,每个文件条目还包含条目的属性、上次修改时间和日期、起始群集索引和条目大小(以字节为单位)。

文件分配

FileX 支持 FAT 格式的标准群集分配方案。 此外,FileX 还支持对连续群集进行预分配。 为此,创建每个 FileX 文件时均未分配群集。 可应后续写入请求或 fx_file_allocate 请求分配群集,以预分配连续群集。

图 4“FileX FAT-16 文件示例”显示了一个名为 FILE.TXT 的文件,向该文件分配了两个连续群集,始于群集 101,大小为 26,且字母表为该文件第一个数据群集号 101 中的数据。

文件访问

可以同时打开多次 FileX 文件以进行读取访问。 但是,写入时,文件只能打开一次。 FX_FILE 文件控制块中包含用于支持文件访问的信息。

注意

请注意,媒体驱动程序可以动态设置写入保护。 如果发生这种情况,那么所有写入请求以及尝试打开用于写入的文件都会被拒绝。

ExFAT 中的文件布局

如果数据存储在连续群集中,则 exFAT 的设计无需为文件维护 FAT 链。 “流扩展目录条目”中的 NoFATChain 位表示从文件中读取数据时是否应使用 FAT 链。 如果设置了 NoFATChain,则 FileX 会从“流扩展目录条目”的“第一个群集”字段指示的群集中依次进行读取。

另一方面,如果清除 NoFATChain,则 FileX 将遵循 FAT 链以遍历整个文件,这与 FAT12/16/32 中的 FAT 链类似。

图 3 显示了两个示例文件,一个无需 FAT 链,另一个则需要 FAT 链。

系统信息

FileX 系统信息包含跟踪打开的介质实例并维护全局系统时间和日期。

具有连续群集的文件 vs. 需要 FAT 链接的文件

图 3。 具有连续群集的文件 vs. 需要 FAT 链接的文件

默认情况下,系统日期和时间设置为 FileX 的上次发布日期。 若要获得准确的系统日期和时间,应用程序必须在初始化期间调用 fx_system_time_set 和 fx_system_date_set。

系统日期

FileX 系统日期在全局 _fx_system_date 变量中进行维护。 第 15 位到第 9 位为相对于 1980 年的年份偏移,第 8 位到第 5 位为月份偏移,而第 4 位到第 0 位为日期。 |

系统时间

FileX 系统时间在全局 _fx_system_time 变量中进行维护。 第 15 位到第 11 位为小时,第 10 位到第 5 位为分钟,而第 4 位到第 0 位则为秒数的一半。

定期时间更新

在系统初始化过程中,FileX 会创建一个 ThreadX 应用程序计时器,以便定期更新系统日期和时间。 系统日期和时间更新速度取决于 _fx_system_initialize 函数使用的两个常量。

常量 FX_UPDATE_RATE_IN_SECONDS 和 FX_UPDATE_RATE_IN_TICKS 表示相同时间段。 常量 FX_UPDATE_RATE_IN_TICKS 是表示秒数(由常量 FX_UPDATE_RATE_IN_SECONDS 指定)的 ThreadX 计时器时钟周期数。 FX_UPDATE_RATE_IN_SECONDS 常量指定每次 FileX 时间更新之间的秒数。 因此,内部 FileX 时间以 FX_UPDATE_RATE_IN_SECONDS 的间隔递增。 在 fx_system_initialize 编译过程中,可能会提供这些常量,或者开发人员可能修改在 FileX 版本的 fx_port.h 文件中找到的默认值。

定期 FileX 计时器仅用于更新全局系统日期和时间,而该日期和时间仅用于文件时间戳。 如果无需时间戳,只需在编译 fx_system_initialize.c 时定义 FX_NO_TIMER,以避免创建 FileX 定期计时器。

FileX FAT-16 文件示例

图 4. FileX FAT-16 文件示例