文件缓存
默认情况下,Windows 缓存从磁盘读取的和写入到磁盘的文件数据。 这意味着读取操作从系统内存中称为系统文件缓存的区域读取文件数据,而不是从物理磁盘读取文件数据。 相应地,写入操作将文件数据写入系统文件缓存,而不是写入磁盘。这类缓存称为回写缓存。 缓存按文件对象进行管理。
缓存在 缓存管理器的指导下进行,缓存管理器在 Windows 运行时连续运行。 系统文件缓存中的文件数据按操作系统确定的间隔写入磁盘,并释放该文件数据以前使用的内存,这称为 刷新 缓存。 将数据延迟写入文件并将其保留在缓存中,直到缓存刷新的策略称为延迟写入,由缓存管理器按确定的时间间隔触发。 刷新文件数据块的时间部分取决于该块已在缓存中存储了多长时间,以及自上次在读取操作中访问数据以来已过去多长时间。 这样可确保频繁读取的文件数据在最大时间范围内可以在系统文件缓存中供访问。
下图演示了此文件数据缓存过程。
如上图中的实线箭头所示,当缓存管理器在文件读取操作期间首次请求数据时,会将 256 KB 的数据区域读入系统地址空间中的 256 KB 缓存“槽”。 然后,一个用户模式进程将该槽中的数据复制到它自己的地址空间。 该进程在完成其数据访问操作后,会将更改的数据写回到系统缓存中的同一槽,如进程地址空间和系统缓存之间的虚线箭头所示。 当缓存管理器确定在一定时间内不再需要数据时,它会将更改的数据写回到磁盘上的文件,如系统缓存和磁盘之间的虚线箭头所示。
文件数据缓存提供的 I/O 性能改进量取决于读取或写入的文件数据块的大小。 读取和写入大型文件数据块时,更可能需要磁盘读取和写入才能完成 I/O 操作。 随着更多此类 I/O 操作的发生,I/O 性能将越来越受损。
在这些情况下,可以关闭缓存。 这是在打开文件时完成的,方法是将FILE_FLAG_NO_BUFFERING作为 CreateFile 的 dwFlagsAndAttributes 参数的值传递。 禁用缓存后,所有读取和写入操作都会直接访问物理磁盘。 但是,文件元数据仍可能缓存。 若要将元数据刷新到磁盘,请使用 FlushFileBuffers 函数。
刷新的频率是平衡系统性能和系统可靠性的一个重要考虑因素。 如果系统过于频繁地刷新缓存,则引发的大型写入操作刷新次数将显著降低系统性能。 如果系统刷新频率不够高,则缓存耗尽系统内存或系统突然故障 ((例如计算机断电) 刷新前发生)的可能性更大。 在后一个实例中,缓存的数据将丢失。
为了确保发生适当的刷新量,缓存管理器每隔一秒生成一个进程,称为延迟编写器。 延迟编写器进程会将最近未刷新的八分之一的页面排队以写入磁盘。 它会不断重新评估要刷新的数据量,以获得最佳的系统性能,如果需要写入更多数据,它会将更多数据排入队列。 延迟编写器不会刷新临时文件,因为假设它们将由应用程序或系统删除。
某些应用程序(如病毒检查软件)要求其写入操作立即刷新到磁盘;Windows 通过写通缓存提供此功能。 进程通过将 FILE_FLAG_WRITE_THROUGH 标志传递到对 CreateFile 的调用中,为特定 I/O 操作启用写通缓存。 启用写通缓存后,数据仍会写入缓存,但缓存管理器会立即将数据写入磁盘,而不会因使用延迟编写器而产生延迟。 进程还可以通过调用 FlushFileBuffers 函数强制刷新已打开的文件。
始终缓存文件系统元数据。 因此,若要将任何元数据更改存储到磁盘,必须刷新文件或使用 FILE_FLAG_WRITE_THROUGH打开。