文件缓冲

本主题介绍应用程序控制文件缓冲的各种注意事项,也称为未缓冲文件输入/输出 (I/O) 。 文件缓冲通常由后台的系统处理,除非另有说明,否则会被视为 Windows 操作系统中 文件缓存 的一部分。 尽管术语 缓存缓冲 有时可互换使用,但本主题在说明如何与未缓存 (系统) 缓冲的数据进行交互的上下文中专门使用了“ 缓冲 ”这两个术语,否则在很大程度上不受用户模式应用程序的直接控制。

使用 CreateFile 函数打开或创建文件时,可以指定 FILE_FLAG_NO_BUFFERING 标志来禁用从文件读取或写入文件的数据的系统缓存。 尽管这可以完全直接控制数据 I/O 缓冲,但对于文件和类似设备,必须考虑数据对齐要求。

注意

此对齐信息适用于设备(例如支持查找的文件)上的 I/O,以及文件位置指针的概念 (或 偏移 量) 。 对于不查找的设备(例如命名管道或通信设备),关闭缓冲可能不需要任何特定的对齐方式。 在这种情况下,一致性可能获得的任何限制或效率都取决于基础技术。

 

在一个简单的示例中,应用程序将使用 FILE_FLAG_NO_BUFFERING 标志打开一个文件进行写入访问,然后使用应用程序中定义的数据缓冲区对 WriteFile 函数执行调用。 在这种情况下,此本地缓冲区实际上是此操作唯一存在的文件缓冲区。 由于物理磁盘布局、文件系统存储布局和系统级文件指针位置跟踪,此写入操作将失败,除非本地定义的数据缓冲区满足某些对齐条件(如下部分所述)。

注意

关于缓存的讨论不考虑物理磁盘本身上的任何硬件缓存,这不能保证在任何情况下都属于系统的直接控制范围。 这不会影响本主题中指定的要求。

 

有关 FILE_FLAG_NO_BUFFERING 如何与其他缓存相关标志交互的详细信息,请参阅 CreateFile

对齐和文件访问要求

如前所述,使用 FILE_FLAG_NO_BUFFERING打开的文件时,应用程序必须满足某些要求。 以下具体细节适用:

  • 文件访问大小(包括 OVERLAPPED 结构中的可选文件偏移量)(如果指定)必须为卷扇区大小的整数倍的字节数。 例如,如果扇区大小为 512 字节,则应用程序可以请求读取和写入 512、1,024、1,536 或 2,048 字节,但不能请求 335、981 或 7,171 字节。
  • 读取和写入操作的文件访问缓冲区地址应与物理扇区对齐,这意味着在内存中是卷物理扇区大小的整数倍的地址上对齐。 根据磁盘的不同,可能不会强制实施此要求。

应用程序开发人员应注意将新类型的存储设备引入市场,其物理媒体扇区大小为 4,096 字节。 这些设备的行业名称为“高级格式”。 由于直接引入 4,096 字节作为媒体寻址单元可能存在兼容性问题,临时兼容性解决方案是引入模拟常规 512 字节扇区存储设备的设备,但通过标准 ATA 和 SCSI 命令提供有关真实扇区大小的信息。

由于这种模拟,开发人员需要了解本质上有两个扇区大小:

  • 逻辑扇区:用于媒体的逻辑块寻址的单元。 还可以将其视为存储可以接受的最小写入单位。 这是“仿真”。
  • 物理扇区:在单个操作中完成对设备的读取和写入操作的单元。 这是原子写入的单元,需要与哪些非缓冲区 I/O 保持一致,以获得最佳性能和可靠性特征。

大多数最新的 Windows API(如 IOCTL_DISK_GET_DRIVE_GEOMETRYGetDiskFreeSpace)将返回逻辑扇区大小,但物理扇区大小可以通过IOCTL_STORAGE_QUERY_PROPERTY控制代码进行检索,相关信息包含在 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR 结构的 BytesPerPhysicalSector 成员中。 有关示例,请参阅 STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR 中的示例代码。 Microsoft 强烈建议开发人员将无缓冲区 I/O 与 IOCTL_STORAGE_QUERY_PROPERTY 控制代码报告的物理扇区大小保持一致,以帮助确保其应用程序为此扇区大小转换做好准备。

Windows Server 2003 和 Windows XP:STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR结构不可用。 它是在 Windows Vista 和 Windows Server 2008 中引入的。

由于读取和写入操作的缓冲区地址必须与扇区对齐,因此应用程序必须直接控制这些缓冲区的分配方式。 扇区对齐缓冲区的一种方法是使用 VirtualAlloc 函数来分配缓冲区。 考虑以下情况:

  • VirtualAlloc 分配在地址上对齐的内存,这些地址是系统页面大小的整数倍数。 x64 和 x86 上的页面大小为 4,096 字节,对于基于 Itanium 的系统,页大小为 8,192 字节。 有关其他信息,请参阅 GetSystemInfo 函数。
  • 对于直接访问存储设备,扇区大小通常为 512 到 4,096 字节, (硬盘驱动器) ,对于 CD-ROM,扇区大小为 2,048 字节。
  • 页大小和扇区大小均为 2。

因此,在大多数情况下,页对齐内存也将是扇区对齐的,因为扇区大小大于页面大小的情况很少见。

获取手动对齐内存缓冲区的另一种方法是使用 C Run-Time 库中的 _aligned_malloc 函数。 有关如何手动控制缓冲区对齐方式的示例,请参阅 WriteFile 的示例代码部分中的 C++ 语言代码示例。