本文摘自(
support.microsoft.com/kb/156932/zh-tw)
在 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。 本文使用下列名詞同步及非同步進行 I / O 作業在 Windows NT。 這份文件假設將讀取器有特定的檔案 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);
請注意, & NumberOfBytesTransferred 傳入 GetOverlappedResult 與傳入 ReadFile NumberOfBytesRead 有所不同 如果作業後成為非同步, 則是用來判斷實際的作業中在它完成後傳送的位元組數目 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 壓縮是一個障礙至非同步作業。 檔案系統驅動程式將無法存取壓縮的檔案以非同步方式 ; 而所有作業是剛建立同步。 這不適用於利用類似於 COMPRESS 或 PKZIP 公用程式壓縮的檔案。
延伸檔案
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 不提供非同步頁面錯誤機制, 以管理由快取記憶體管理員所使用檔案對應。 快取管理員可以不過, 驗證您所要求的網頁是否在記憶體, 如果您發出非同步快取的讀取, 且頁面是不在記憶體, 檔案系統驅動程式假設您不要封鎖您的執行緒並要求將處理由的背景工作執行緒 (Worker Thread) 集有限區。 在使用唯讀仍然暫止 ReadFile 呼叫您的控制項傳回給您的程式。
這適用於少量的要求, 正常有限制 (三目前個 16 MB 系統上), 但因為集區的背景工作執行緒 (Worker Thread) 是將仍然只有幾要求佇列到磁碟驅動程式在特定時間 如果您發出大量的 I / O 作業對資料, 且該檔案不在快取, 成為飽和快取記憶體管理員和記憶體管理員並將設為同步您的要求。
可以快取管理員的行為也會影響根據您是否連續或隨機存取檔案。 循序存取檔案時快取的優點最看到是。 在呼叫 CreateFile FILE_FLAG_SEQUENTIAL_SCAN 旗標會最佳化快取為這類型的存取。 指示快取記憶體管理員, 以最佳化其行為進行隨機存取不過, 如果您存取檔案以隨機方式, 用來 FILE_FLAG_RANDOM_ACCESS 旗標 CreateFile 中。
請不要使用快取
檔案系統來進行非同步作業的行為上 FILE_FLAG_NO_BUFFERING 旗標有大部分的效果。 這是最好的方法, 以保證是實際上非同步 I / O 要求。 它指示檔案系統為根本不使用任何快取機制。
警告 : 有一些限制, 對資料緩衝區對齊和裝置的磁扇區大小必須在使用這個旗標 請參閱 CreateFile 函式需正確地使用這個旗標的詳細資訊在文件中函式中的參考。
SAMPLE CODE
您可以從「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.
實際的測試結果
以下是一些測試結果和範例程式碼。 大量的數字就在這裡並不重要和, 在電腦而有所不同但編號相較於彼此的關聯性 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. 這個程式, 而測試 1 花費只有 0.224264 秒鐘來發出相同要求呼叫來完成其作業, ReadFile 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.
CONCLUSION您可以決定最好的方法因為它所有相依於型別、 大小和的作業, 您的程式會執行數。
但未指定任何特殊旗標來 CreateFile 預設檔案存取是同步和快取的操作。
請注意 : 您在這個模式下取得某些自動非同步行為, 因為檔案系統驅動程式做預測非同步預先讀取 - 和非同步 (Asynchronous) 延遲寫入的修改過的資料 雖然這並不會讓應用程式 [ ASCII ] 146 s I / O 非同步, 但它是對於絕大部分簡單的應用程式理想情況。
如果您的應用程式是在另一方面, 不是簡單, 您必須進行一些程式碼剖析和效能監視來判斷最適合的方法類似於稍早在本篇文章說明測試。 程式碼剖析時間花在 ReadFile 或 WriteFile 函式而然後比較要多久才會進行實際的 I / O 作業來完成這一次是非常有用。 如果大多數的時間是花在實際上是發出 I / O, 則您的 I / O 是正在完成同步。 相較於則被視為非同步您的作業時間進行 I / O 作業來完成, 不過, 如果發出的 I / O 要求所花費的時間為相對較小。 在本篇文章稍早提到範例程式碼使用 QueryPerformanceCounter 函式進行它自己的內部程式碼剖析。
效能監視可幫您判斷如何有效地您的程式正在使用磁碟和快取。 追蹤任何的效能計數器為快取物件會指出效能的快取記憶體管理員。 追蹤對於實體磁碟 」 或邏輯磁碟物件中的效能計數器會指出磁碟系統的效能。
有一些公用程式所有用在效能監視 ; PerfMon 和 DiskPerf 是特別有用。 為系統來收集資料對效能的磁碟系統, 您必須先發出 diskperf - y 命令的。 您發出指令之後, 您必須重新系統來啟動資料收集。
参考更多有關如何這些公用程式和效能監視器, 請參魷 \\cs6 \\f1 \\cf6 \\lang1024 磁碟區在 Windows NT Resource Kit 文件中 < Optimizing Windows NT >。
這篇文章中的資訊適用於:
• |
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 | |
這項測試會示範在測試 3 為相同的結果。 請注意從快取中, 從快取同步讀取完成稍微比非同步讀取。 當資料是在快取這項測試也示範高效能的快取記憶體管理員。 |
範例: / asynchio /f*.bmp n
這個程式的預設操作是針對非同步且已緩衝的作業。 根據預設值, 500 個 I / O 作業要求。