你目前正处于脱机状态,正在等待 Internet 重新连接

异步磁盘 I/O 出现在 Windows 上同步

重要说明:本文是由 Microsoft 机器翻译软件进行的翻译并可能由 Microsoft 社区通过社区翻译机构(CTF)技术进行后期编辑,或可能是由人工进行的翻译。Microsoft 同时向您提供机器翻译、人工翻译及社区后期编辑的文章,以便对我们知识库中的所有文章以多种语言提供访问。翻译的文章可能存在词汇、句法和/或语法方面的错误。Microsoft 对由于内容的误译或客户对内容的使用所导致的任何不准确、错误或损失不承担责任。

156932
概要
Microsoft Windows 上的文件 I/O 可以是同步或异步的。其中 I/O 函数调用和返回 I/O 完成后,I/O 的默认行为是同步的。异步 I/O 允许立即返回到调用方执行 I/O 函数,但是 I/O 不假定将来的某个时间才会完成。I/O 完成时,操作系统将通知调用方。另外,调用方可以通过使用操作系统的服务确定未完成的 I/O 操作的状态。

利用异步 I/O 是调用方有时间来做其他工作,或发出多个请求,而正在完成 I/O 操作。一词重叠我/Ois 经常用于异步 I/O 和非重叠 I/O 同步 I/O。本文使用 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。
更多信息

设置异步 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 操作。示例代码演示了这一点。

有很多事情,一个程序可以执行而等待 asynchronousoperations 来完成,如队列的附加操作或 doingbackground 的工作。例如,下面的代码正确 handlesoverlapped 和非重叠的读取操作完成。它 doesnothing 多等待未完成的 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 用于确定在它后面的操作中所传输的字节的实际数目 hascompleted。& NumberOfBytesRead 传递到 ReadFile 毫无意义。

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

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

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

异步 I/O 仍显示同步

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

有的为什么 I/O 操作完成 synchronouslyeven,如果有编码的异步操作的原因有多种:

压缩

异步操作的一个障碍是 NTFS 压缩。文件系统驱动程序将不会异步; 访问压缩的文件而是 alloperations 只是进行同步。这不适用于文件与实用程序类似于压缩或于 PKZIP 的 arecompressed。

NTFS 的加密

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

扩展文件

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

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

应用程序使用 SetFileValidData (这是 Windows XP 和更高版本上提供),可以有效地扩展多文件而不会带来性能损失为零填充它们。

因为 NTFS 文件系统没有零填充之前由 SetFileValidData 定义的有效数据长度 (VDL) 的数据,此函数具有的安全隐患,文件可能会分配为其他文件先前占用的群集。因此,SetFileValidData 要求调用方具有启用新 SeManageVolumePrivilege (默认情况下,这只分配给管理员)。Microsoft 建议 Isv 仔细考虑使用此函数的问题。

高速缓存

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

数据不在高速缓存

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

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

缓存管理器的行为也会影响基于无论访问文件按顺序或随机。按顺序访问的文件时,缓存的好处是 seenmost。FILE_FLAG_SEQUENTIAL_SCAN flagin CreateFile 调用将这种访问的高速缓存进行优化。但是,如果您访问文件以随机的方式,用 theFILE_FLAG_RANDOM_ACCESS 标志 CreateFile 来指示其行为进行随机访问的高速缓存管理器 tooptimize。

不使用高速缓存

FILE_FLAG_NO_BUFFERING 标志大多数起了 thefile 系统的异步操作的行为。这是的 guaranteethat I/O 请求是异步实际上的最佳方法。它指示该文件 systemto 根本不使用任何缓存机制。

警告: 使用此标志所要使用的数据缓冲区对齐方式和设备的扇区大小做某些受限制。请参阅有关如何正确使用此标志的 CreateFile 函数的文档中的函数引用。

实际测试结果

下面是一些示例代码中的测试结果。量的 thenumbers 在此处并不重要,不同计算机之间但亮 thegeneral 的标志对性能影响互相比较的数字的关系。

您会看到类似如下的结果:
  • 测试 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.						
    此测试演示该程序花费调用 ReadFile 完成其操作,而该测试 1 花费仅为 0.224264 秒发出相同请求的 4.495880 秒。在测试 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 相同的结果。请注意,同步从缓存读取速度比异步读取完成从缓存。在缓存中的数据时,此测试还演示缓存管理器的高性能。

结论

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

缺省文件而无需指定任何特殊的标志,以 CreateFileis 同步和缓存操作访问。

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

如果,另一方面,您的应用程序并不简单,您可能必须为 dosome 分析和性能监视可确定最佳的方法,类似于本文前面所示的测试。分析时所用的 theReadFile 或写文件函数,然后比较这方式一次长它 takesfor 实际的 I/O 操作完成时非常有用。如果 majorityof 在实际发出的 I/O,然后 I/O 所花费的时间同步是 beingcompleted。但是,如果与比较花费时间颁发 I/O 请求 isrelatively 小的时间计为 I/O 操作 tocomplete,则以异步方式处理操作。本文前面提到的 samplecode 使用 QueryPerformanceCounter 函数来执行其 owninternal 分析。

性能监视可以帮助您确定如何有效程序 isusing 磁盘和缓存。跟踪任何缓存对象的性能计数器将指示缓存管理器的性能。物理磁盘或逻辑 Diskobjects 跟踪性能计数器将指示磁盘系统的性能。

有几个实用程序可有助于性能监视;性能监控和 DiskPerf 程序特别有用。收集数据的磁盘系统的性能的系统,您必须首先发出 diskperf-y 命令。发出命令后,您必须重新启动系统以启动数据收集。
参考
请参阅 MSDN 文档上 同步和异步 I/O 其他信息。

Asynczip ReadFileEx ReadFile WriteFile kbdss kbfile WriteFileEx GetOverlappedResult 异步同步重叠非重叠模式

警告: 本文已自动翻译

属性

文章 ID:156932 - 上次审阅时间:02/09/2016 05:12:00 - 修订版本: 8.0

  • Microsoft Win32 Application Programming Interface
  • kbapi kbfileio kbinfo kbkernbase kbmt KB156932 KbMtzh
反馈