文件缓冲

本主题介绍应用程序控制文件缓冲的各种注意事项,也称为无缓冲文件输入/输出(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 打开的文件时,必须满足某些要求。 以下具体细节适用:

  • 文件访问大小,包括 重叠 结构中的可选文件偏移量(如果指定),必须为卷扇区大小的整数倍的字节数。 例如,如果扇区大小为 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强烈建议开发人员根据 IOCTL_STORAGE_QUERY_PROPERTY 控制代码报告,将无缓冲区 I/O 与物理扇区大小保持一致,以帮助确保其应用程序已准备好进行此扇区大小转换。

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++语言代码示例。

文件缓存

CreateFile

写入文件