异步磁盘 I/O 将出现在 Windows NT、 Windows 2000 和 Windows XP 上同步

文章翻译 文章翻译
文章编号: 156932 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

在 Microsoft Windows NT、 Windows 2000 和 Windows XP 文件 I/O 可以是同步或异步。I/O 的默认行为是同步的: 一个 I/O 函数调用和返回 I/O 完成后。异步 I/O,另一方面,允许立即返回到调用方执行 I/O 函数但 I/O 则不认为是为将来的某个时间之前完成。在 I/O 完成后,系统将通知调用方。另外,调用方可以通过使用操作系统的服务确定未完成的 I/O 操作的状态。

异步 I/O 的优点在于调用方必须执行其他的时间正常工作,或正在完成 I/O 操作的同时发出更多请求。"术语 Overlapped I/O 经常用于异步 I/O 和非重叠同步 I/O 的 I/O。本文使用的术语异步和在 Windows NT 下的 I/O 操作的同步。本文假定读取器已熟悉的文件 I/O 功能,例如 CreateFile,某些ReadFile,写文件。

通常情况下,异步 I/O 操作的行为就像同步 I/O。 某些这篇文章在后面几节中讨论的条件使 I/O同步完成的操作。调用方具有背景没有时间由于 I/O 函数不返回 I/O 直至完成工作。

与同步和异步 I/O 相关的多个函数。本文作为示例 ; 使用 ReadFile 和写文件ReadFileEx 和 WriteFileEx,就是很好的替代方案。尽管这篇文章专门讨论了磁盘 I/O 的许多原则可以应用到其它类型的 I/O,例如,串行 I/O 或网络 I/O。

注意: 因为 Windows 95 不支持异步 I/O 在磁盘设备上 (尽管它不会在其他类型的输入/输出设备上),这篇文章中未涵盖的行为。

更多信息

设置异步 I/O

在打开文件时,必须在 CreateFile 中指定 FILE_FLAG_OVERLAPPED 标志。此标志允许要异步执行的文件上的 I/O 操作。下面是一个示例:
   HANDLE hFile;

   hFile = CreateFile(szFileName,
                      GENERIC_READ,
                      0,
                      NULL,
                      OPEN_EXISTING,
                      FILE_FLAG_NORMAL | FILE_FLAG_OVERLAPPED,
                      NULL);

   if (hFile == INVALID_HANDLE_VALUE)
      ErrorOpeningFile();
				
编码为异步 I/O,因为系统保留时要小心要使操作同步,如果它需要的权限。因此,它是最佳如果您编写的程序来进行正确处理的 I/O 操作可能会在同步或异步完成的。示例代码演示了这一点。

有很多事情,程序可以执行而正在等待异步若要完成,如队列的附加操作,或执行的操作后台工作。例如,下面的代码正确处理重叠和非重叠的读取操作的完成。它任何多等待未完成的 i/o 操作来完成:
   if (!ReadFile(hFile,
                 pDataBuf,
                 dwSizeOfBuffer,
                 &NumberOfBytesRead,
                 &osReadOperation )
   {
      if (GetLastError() != ERROR_IO_PENDING)
      {
         // Some other error occurred while reading the file.
         ErrorReadingFile();
         ExitProcess(0);
      }
      else
         // Operation has been queued and
         // will complete in the future.
         fOverlapped = TRUE;
   }
   else
      // Operation has completed immediately.
      fOverlapped = FALSE;

   if (fOverlapped)
   {
      // Wait for the operation to complete before continuing.
      // You could do some background work if you wanted to.
      if (GetOverlappedResult( hFile,
                               &osReadOperation,
                               &NumberOfBytesTransferred,
                               TRUE))
         ReadHasCompleted(NumberOfBytesTransferred);
      else
         // Operation has completed, but it failed.
         ErrorReadingFile();
   }
   else
      ReadHasCompleted(NumberOfBytesRead);
				
请注意,& NumberOfBytesRead 传递到 ReadFile 是不同的& NumberOfBytesTransferred 传递到 GetOverlappedResult。如果操作进行异步操作,然后用 GetOverlappedResult 来确定它后,在操作中传输的字节的实际数目完成。& NumberOfBytesRead 传递到 ReadFile 毫无意义。

如果,相反,操作将立即完成,然后& NumberOfBytesRead 传递到 ReadFile 无效,读取的字节数。在这种情况下,忽略 OVERLAPPED 结构传递到 ReadFile ;不要使用它与 GetOverlappedResult 或 WaitForSingleObject。

与异步操作的其他需要说明的是您必须使用 OVERLAPPED 结构,直到其挂起的操作都已完成。在其他词,如果您有三个未完成的 I/O 操作,必须使用三个 OVERLAPPED 结构。如果重用 OVERLAPPED 结构时,您将收到不可预知的结果,在 I/O 操作中,您可能会遇到数据损坏。此外,在第一次使用 OVERLAPPED 结构之前或早期操作完成后,会重用它之前,您正确必须将其初始化,因此任何剩余的数据会不影响新的操作。

相同类型的限制适用于在中使用的数据缓冲区操作。数据缓冲区必须不能读取或写入之前其相应 I/O 操作已完成。读取或写入缓冲区可能会导致错误和损坏的数据。

异步 I/O 仍显示同步

如果您按照本文前面的说明,但是,所有的 I/O 操作仍通常同步的顺序完成签发的和任何 ReadFile 操作返回 FALSE 的 GetLastError() 返回 ERROR_IO_PENDING,这意味着您必须没有任何背景的工作时间。为什么会这样?

有多种原因,为什么同步 I/O 操作完成即使您原来的异步操作的代码:

压缩

异步操作的一个障碍是 NTFS 压缩。该文件系统驱动程序将不会以异步方式 ; 访问压缩的文件而是所有只需进行同步操作。这不适用于文件使用类似于压缩或 PKZIP 的实用程序进行压缩。

NTFS 的加密

类似于压缩,文件加密将导致系统驱动程序转换到同步的异步 I/O。如果文件被解密,输入/输出请求将是异步的。

扩展文件

I/O 操作同步完成的另一个原因是自己操作。在 Windows NT 上任何写操作扩展其长度的文件将被同步。

注意: 应用程序可创建前面提到的写操作异步通过使用 SetFileValidData 函数,然后颁发写文件更改的文件的有效数据长度。

应用程序使用 SetFileValidData (这是在 Windows XP 和更高版本中可用),可以有效地扩展多文件而不会导致零填充它们会造成性能下降。

因为 NTFS 文件系统却没有零填充之前由 SetFileValidData 定义的有效数据长度 (VDL) 的数据,此函数具有安全意义,文件可能会分配为以前被其他文件占用的群集。因此,SetFileValidData,要求调用方具有启用新 SeManageVolumePrivilege (默认情况下,这只分配给管理员)。Microsoft 建议独立软件供应商认真考虑使用此功能的问题。

高速缓存

大多数 I/O 驱动程序 (磁盘、 通信和其他人) 具有特殊案例的代码位置,如果可以"立即"完成的 I/O 请求,将完成操作,并且 ReadFile 或写文件函数将返回 TRUE。在所有的方面,这些类型的操作看起来是同步的。磁盘设备,通常情况下,可以"立即"时将数据缓存在内存中完成的 I/O 请求。

数据不在高速缓存

缓存方案可以对您,但是,如果数据不在高速缓存。Windows NT 缓存是内部使用文件映射来实现的。在 Windows NT 中的内存管理器不提供异步页容错机制,用于管理缓存管理器使用的文件映射。"缓存管理器可以,但是,验证所请求的页是否在内存中,因此如果您发出异步缓存的读取,而不在内存中的页,文件系统驱动程序假定您不希望您的线程被阻止,并将有限的辅助线程池处理该请求。ReadFile 呼叫仍有待于读后控制返回到您的程序。

这工作正常的少数几个请求,因为的辅助线程池,但那里限制 (当前上有三个 16 MB 系统),将仍然只有几个请求排队到磁盘驱动程序在特定的时间。如果发出了大量的数据不在高速缓存中的 I/O 操作时,达到饱和的高速缓存管理器和内存管理器,您的请求进行同步。

也可以根据是否影响行为的高速缓存管理器按顺序或随机访问文件。显示高速缓存的好处大多数时按顺序访问的文件。FILE_FLAG_SEQUENTIAL_SCAN 标志在 CreateFile 中调用将此类型的访问的高速缓存进行优化。但是,如果您访问以随机方式的文件,请使用FILE_FLAG_RANDOM_ACCESS CreateFile,以指示高速缓存管理器中的标志优化用于随机访问的行为。

不使用高速缓存

FILE_FLAG_NO_BUFFERING 标志产生最大影响的行为异步操作的文件系统。这是最佳的方法,以保证输入/输出请求是异步的实际。它指示的文件系统不要使用任何缓存机制根本。

警告: 有使用此标志一些需要处理的数据的缓冲区对齐方式和设备的扇区大小的限制。请参阅有关正确使用此标志的详细信息的 CreateFile 函数的文档中的函数引用。

实际测试结果

下面的代码示例从某些测试结果。量编号,这里并不重要,各不相同的计算机到计算机,但亮互相比较的数字之间的关系在性能上标志的一般会影响。

您可能会看到类似于以下内容的结果:
  • 测试 1
    Asynchronous, unbuffered I/O:  asynchio /f*.dat /n
    
       Operations completed out of the order in which they were requested.
       500 requests queued in 0.224264 seconds.
       500 requests completed in 4.982481 seconds.
    						
    此测试演示前面提到的程序快速发出 500 的输入/输出请求并有大量的时间来执行其他工作或发出更多请求。
  • 测试 2
    Synchronous, unbuffered I/O: asynchio /f*.dat /s /n
    
       Operations completed in the order issued.
       500 requests queued and completed in 4.495806 seconds.
    						
    此测试演示此程序花费 4.495880 秒为单位)调用 ReadFile 完成其操作,而该测试 1花了 0.224264 秒只发出相同请求。在测试 2 时,人们就没有"额外"的时间要做任何背景的程序正常工作。
  • 测试 3
    Asynchronous, buffered I/O: asynchio /f*.dat
    
       Operations completed in the order issued.
       500 requests issued and completed in 0.251670 seconds.
    						
    此测试演示缓存的同步特性。所有读取已发出,并在 0.251670 秒内完成。换句话说,已同步完成的异步请求。这也测试当数据位于演示的高性能缓存管理器高速缓存。
  • 测试 4
    Synchronous, buffered I/O: asynchio /f*.dat /s
    
       Operations completed in the order issued.
       500 requests and completed in 0.217011 seconds.
    						
    此测试演示测试 3 相同的结果。请注意同步读取缓存中的异步读取操作比任何时候都更快完成从高速缓存。当数据在缓存中时,此测试还演示缓存管理器的高性能。

结论

您可以决定哪一种方法是最佳的因为这完全取决于的类型、 大小和在程序执行的操作的数量。

缺省文件访问,而无需指定任何特殊标志为 CreateFile是一个同步和缓存操作。

注意: 不要在此模式下获得某些自动异步行为,因为文件系统驱动程序不会预测异步预读和异步惰性写入修改后的数据。虽然这不会使应用程序 [ASCII 146] s I/O 异步,它是理想情况下,对于简单的应用程序的绝大多数。

如果,相反,您的应用程序不是简单的您可能需要执行操作一些分析和性能监视,以确定最佳的方法,类似于本文前面所述的测试。性能分析时所用的ReadFile 或写文件的函数,然后比较这方式一次长时间越长实际 I/O 操作完成时非常有用。如果大多数时间花费在实际上颁发 I/O,然后 I/O 正在同步完成。但是,如果所用的时间的颁发的输入/输出请求是相对较小与时间比较它与 I/O 操作的时间完成后,然后您的操作被视为以异步方式。该示例本文中前面所述的代码使用 QueryPerformanceCounter 函数来执行它自己内部分析。

性能监视可帮助确定您的程序是如何有效地使用磁盘和高速缓存。跟踪所有的性能计数器高速缓存对象将会显示高速缓存管理器的性能。跟踪为物理磁盘的逻辑磁盘的性能计数器对象将会显示磁盘系统的性能。

有多个实用程序可有助于性能监视 ;性能监控和 DiskPerf 将非常有用。对性能的磁盘系统收集数据的系统,您必须首先发出 diskperf-y 命令。发出命令后,您必须重新启动系统,以启动数据收集。

参考

有关这些实用程序和性能监视的详细信息,请参阅在 Windows NT 资源中的"优化 Windows NT"的卷包文档。
SQL Server 要求系统,以支持 Microsoft SQL Server Always-On 存储解决方案审查计划下所述的保证的传递到稳定的媒体。Fo有关 SQL Server 数据库引擎的输入和输出要求的详细信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
967576Microsoft SQL Server 数据库引擎的输入/输出要求

属性

文章编号: 156932 - 最后修改: 2013年5月30日 - 修订: 6.0
这篇文章中的信息适用于:
  • Microsoft Win32 Application Programming Interface
  • Microsoft SQL Server 2008 Developer
  • Microsoft SQL Server 2008 Enterprise
  • Microsoft SQL Server 2008 Express
  • Microsoft SQL Server 2008 Standard
关键字:?
kbapi kbfileio kbinfo kbkernbase kbmt KB156932 KbMtzh
机器翻译
重要说明:本文是由 Microsoft 机器翻译软件进行的翻译并可能由 Microsoft 社区通过社区翻译机构(CTF)技术进行后期编辑,或可能是由人工进行的翻译。Microsoft 同时向您提供机器翻译、人工翻译及社区后期编辑的文章,以便对我们知识库中的所有文章以多种语言提供访问。翻译的文章可能存在词汇、句法和/或语法方面的错误。Microsoft 对由于内容的误译或客户对内容的使用所导致的任何不准确、错误或损失不承担责任。
点击这里察看该文章的英文版: 156932
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com