文章編號: 156932 - 上次校閱: 2009年2月6日 - 版次: 5.1

非同步磁碟 I/O 出現為 Windows NT、 Windows 2000 和 Windows XP 上同步

在此頁中

全部展開 | 全部摺疊

結論

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 作業完成後發出多個要求。 不重疊的 I/O 非同步 I/O 以及經常使用詞彙 Overlapped I/O 的同步 I/O。 這份文件會使用在 Windows NT 的 I/O 作業條款非同步和同步。 本文假設讀者有某些熟悉 「 檔案 I/O 功能 (例如 CreateFile,ReadFile,WriteFile。

經常,非同步 I/O 作業行為只同步 I/O 這篇文章討論在稍後的章節產生同步 I/O 作業完成的某些條件。 呼叫端有沒有背景工作的時間,因為 I/O 函式不會傳回 I/O 完成之前。

同步和非同步 I/O 與有幾個函式。 這份文件所使用的 ReadFile 和 WriteFile 做為範例 ; 很好的替代方案是 ReadFileEx 和 WriteFileEx。 雖然本文將討論磁碟 I/O 特別,許多原則可以套用至其他類型的 I/O,例如序列 I/O 或網路 I/O。

注意 : 由於 Windows 95 不支援非同步 I/O 磁碟裝置上 (雖然它不會在其他類型的 I/O 裝置上),本文不討論它的行為。

其他相關資訊

設定非同步 I/O

在開啟檔案時,必須指定 FILE_FLAG_OVERLAPPED 旗標 CreateFile 中。 此旗標允許以非同步方式執行檔案 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);
				
請注意,傳遞至 ReadFile NumberOfBytesRead 是不同的 & NumberOfBytesTransferred 傳入 GetOverlappedResult。 如果作業已非同步,GetOverlappedResult 是會用來判斷它完成後,在作業中傳輸的位元組實際數目。 &NumberOfBytesRead 傳入 ReadFile 是無意義。

如果在另一方面的作業完成時立即,然後 & NumberOfBytesRead 傳入 ReadFile 無效的讀取的位元組數。 在這種情況下忽略傳入 ReadFile OVERLAPPED 結構 ; 不要使用它與 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 要求。

延伸檔案

另一個同步完成 I/O 作業的原因是本身的作業。 在 Windows NT 上, 任何寫入作業,以延伸其長度的檔案會同步。

注意 : 應用程式可以讓先前所述的寫入作業非同步藉由使用 SetFileValidData 函式中,並再發出一個 WriteFile 變更檔案的有效資料長度。

使用 SetFileValidData (這是可以在 Windows XP 和更新版本),應用程式可以有效率地擴充檔案而不會為零的填入,它們的效能損失。

因為 NTFS 檔案系統並不為零的填滿資料上有效資料長度 (VDL) 所定義的 SetFileValidData,這個函式會有安全性含意檔案可以指派了先前所佔用的其他檔案的叢集。 因此,SetFileValidData 要求呼叫端有新的 SeManageVolumePrivilege 啟用 (預設情況下,這指派只給系統管理員)。 Microsoft 建議 ISV 請仔細考慮使用這個函式會產生影響。

快取

大部分的 I/O 驅動程式 (磁碟、 通訊,及其他) 有特殊案例程式碼位置,如果的 I/O 要求可以在 「 立即 」 完成,作業將會完成,ReadFile 或 WriteFile 函式會傳回 TRUE。 所有方式這些類型的作業會顯示為同步。 磁碟裝置,一般的 I/O 要求可以完成資料快取記憶體中時,「 立即 」。

資料不在快取中

快取配置能對您,但是,如果資料不在快取中。 Windows NT 快取被實作內部使用檔案對應。 記憶體管理員在 Windows NT 並不提供一個非同步頁面的容錯機制來管理快取管理員所使用的檔案對應。 快取管理員可以但是,驗證要求的網頁是否在記憶體,因此檔案系統驅動程式如果您發出的非同步的快取的讀取,且網頁並不在記憶體中,假設您不想您封鎖的執行緒,並要求將由有限的背景工作執行緒集區。 仍然擱置中讀取與您 ReadFile 呼叫之後將控制項傳回至您的程式。

這可以適用於少量的要求,但因為背景工作執行緒集區是那里限制 (目前三 16 MB 的系統上),將仍只有少數的要求排入磁碟驅動程式在特定的時間。 如果您發出大量的資料不在快取的 I/O 作業,記憶體管理員與快取管理員成為飽和,並且您的要求進行同步。

快取管理員的行為也可以根據是否您存取檔案循序或隨機會影響。 依序存取檔案時,是最看到快取的優點。 在呼叫 CreateFile FILE_FLAG_SEQUENTIAL_SCAN 旗標會最佳化這種類型的存取快取。 但是,如果您存取以隨機的方式中的檔案,使用 [FILE_FLAG_RANDOM_ACCESS 標幟 CreateFile 中來指示快取管理員若要最佳化的隨機存取其行為。

請勿使用快取

FILE_FLAG_NO_BUFFERING 旗標有非同步作業的檔案系統的行為大部分的效果。 這是為了確保有實際的非同步 I/O 要求最佳的方法。 它指示檔案系統,不在使用任何快取機制。

警告 : 有使用這個旗標資料緩衝區的對齊方式與裝置的磁區大小需要一些限制。 請參閱更多有關如何正確使用這個旗標 CreateFile 函式的文件中的函式參考資料。

範例程式碼

從 「 Microsoft 下載中心 」 下載下列檔案有:
Asynczip.exe (http://download.microsoft.com/download/platformsdk/sample/3/nt4/en-us/asynczip.exe)
如需有關如何下載 Microsoft 支援檔案的詳細資訊,按一下 [下文件編號,檢視 「 Microsoft 知識庫 」 中的 「 文件]:
119591? (http://support.microsoft.com/kb/119591/EN-US/ ) 如何從線上服務取得 Microsoft 支援檔案
Microsoft 掃描這個檔案有病毒。 Microsoft 會使用最新病毒偵測軟體的可用檔案已發佈的日期。 檔案儲存在安全的伺服器上,以避免任何未經授權的更改至檔案。 與這份文件相關聯的範例程式碼示範如何使用旗標和函式所討論。 程式碼是在 Windows NT 上執行為主控台應用程式。 下列的命令列參數控制其行為:
   Asynchio
   Usage: asynchio [options]

   Options:
      /fFilePattern  Files to use for I/O.
      /s    Specifies synchronous operation.
      /n    Specifies that no buffering should be used
      /r    Use FILE_FLAG_RANDOM_ACCESS
      /l    Use FILE_FLAG_SEQUENTIAL_SCAN
      /o###    Issue ### operations
      /e    First read entire file, then issue smaller reads
      /?    Display this usage message.
				
範例: asynchio /f*.bmp /n
這個程式的預設操作是非同步,緩衝的作業。 預設情況下,500 的 I/O 作業會要求。

真實世界的測試結果

以下是一些範例程式碼的測試結果。 數字的大小不重要這裡而且會從電腦對電腦,但數字相較於彼此的關聯性光線照亮一般旗標的效能影響。

您可以預期看到類似下列的結果:
  • 測試 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 的 I/O 要求,以及有很多時間來執行其他工作或發出多個要求。
  • 測試 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 或 WriteFile 函式,然後比較多久才實際 I/O 作業完成這次非常有用。 如果大部分的時間花在實際發行 I/O,然後您的 I/O 完成同步。 但是,如果時間花費發行的 I/O 要求是相當小相較於花費的時間在 I/O 作業完成,然後以非同步方式正在處理您的作業。 本文稍早所述範例程式碼會使用 QueryPerformanceCounter 函式來執行自己內部的設定檔。

效能監視,可以協助決定程式如何有效地使用磁碟和快取。 追蹤任何快取物件的效能計數器會指出快取管理員的效能。 追蹤實體磁碟或邏輯磁碟的物件的效能計數器會指出磁碟系統的效能。

有幾個有用的效能監視的公用程式,; PerfMon 和 DiskPerf 都是特別有用。 讓系統收集磁碟系統的效能資料,您必須先發出 diskperf-y 命令。 發出命令之後,您必須重新啟動系統以啟動資料收集。

?考

更多有關這些公用程式 」 和 「 效能監視,請參閱 Windows NT 資源工具箱 」 文件中的最佳化 Windows NT [磁碟區。
SQL Server 要求系統,以支援 ‘ 保證傳遞到穩定的媒體無法在 Microsoft SQL Server Always-On 儲存方案檢視程式所述。 Fo如更多有關 SQL Server 資料庫引擎的輸入與輸出需求的資訊,按一下下面的文件編號,檢視 「 Microsoft 知識庫 」 中的 「 文件:
967576? (http://support.microsoft.com/kb/967576/ ) Microsoft SQL Server 資料庫引擎的輸入/輸出需求

這篇文章中的資訊適用於:
  • Microsoft Win32 Application Programming Interface?應用於:
    • Microsoft Windows NT 3.51 Service Pack 5
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
  • Microsoft SQL Server 2008 Developer
  • Microsoft SQL Server 2008 Enterprise
  • Microsoft SQL Server 2008 Express
  • Microsoft SQL Server 2008 Standard
關鍵字:?
kbmt kbapi kbfileio kbinfo kbkernbase KB156932 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:156932? (http://support.microsoft.com/kb/156932/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。
 

文章翻譯

 

Related Support Centers