Help and Support

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

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

在此頁中

全部展開 | 全部摺疊

結論

檔案 I / O],在 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 的同步的 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

時開啟檔案,您必須在 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 時讀取的位元組數有效的。 在這種情況下,忽略傳入 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 來變更檔案的有效資料長度。

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

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

快取

大多數的 I / O 驅動程式 (磁碟、 Communications,和其他) 會有特殊大小寫的程式碼位置,如果 I / O 要求可以 「 立即完成,完成作業並 ReadFile 或 WriteFile 函式會傳回 TRUE。 所有方式這些類型的作業會出現於同步。 為磁碟裝置,一般,I / O 要求可以完成記憶體中快取資料時,「 立即 」。

資料不是快取

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

正常可用於要求,少量的但因為背景工作執行緒集區有限制 (目前三 16MB 系統上),將仍然只有少數的要求佇列磁碟驅動程式在特定的時間。 如果您發出大量的 I / O 作業不會快取中的資料,快取經理 」 和 「 記憶體管理員會飽和,「 您的要求所進行同步。

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

不要使用快取

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

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

SAMPLE 程式碼

您可以從 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 作業。

真實世界的測試結果

下列是一些範例程式碼的測試結果時。 數字的範圍不重要這裡而有所不同的電腦,但數字相較於彼此的關聯性 illuminates 旗標,在效能上的 [一般] 造成的影響。

您可以預期會看見類似下列的結果:
  • 測試 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 Resource Kit 文件中的磁碟區 《 最佳化 Windows NT 》 (英文)。
SQL Server 需要的系統,以支援 ‘ 保證傳遞到穩定的媒體 ’ 述在 Microsoft SQL Server 永遠下-儲存解決方案檢視程式上。 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