オーバーラップ I/O でフラグ FILE_FLAG_NO_BUFFERING を使用すると、奇妙な動作が見られます。一連の ReadFile() 関数呼び出しを呼び出し、後で GetOverlappedResult() を使用してそれらのステータスをクエリします。
私が話している奇妙な動作は、ファイルハンドルが良好で、ReadFile() 呼び出しが悪いエラーなしで返された場合でも (予想される ERROR_IO_PENDING を除く)、GetOverlappedResult() 呼び出しから返される「バイト読み取り」値がゼロであるということです。コードを実行するたびに、ファイルのセットが異なります。 FILE_FLAG_NO_BUFFERING を削除すると、正常に動作し始め、読み取り値がゼロになりません。
FILE_FLAG_NO_BUFFERING を使用してオーバーラップ I/O コードを実装する方法を次に示します。
long overlappedIO(std::vector<std::string> &filePathNameVectorRef)
{
long totalBytesRead = 0;
DWORD bytesRead = 0;
DWORD bytesToRead = 0;
std::map<HANDLE, OVERLAPPED> handleMap;
HANDLE handle = INVALID_HANDLE_VALUE;
DWORD accessMode = GENERIC_READ;
DWORD shareMode = 0;
DWORD createDisposition = OPEN_EXISTING;
DWORD flags = FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING;
DWORD fileSize;
LARGE_INTEGER li;
char * buffer;
BOOL success = false;
for(unsigned int i=0; i<filePathNameVectorRef.size(); i++)
{
const char* filePathName = filePathNameVectorRef[i].c_str();
handle = CreateFile(filePathName, accessMode, shareMode, NULL, createDisposition, flags, NULL);
if(handle == INVALID_HANDLE_VALUE){
fprintf(stdout, "\n Error occured: %d", GetLastError());
fprintf(stdout," getting handle: %s",filePathName);
continue;
}
GetFileSizeEx(handle, &li);
fileSize = (DWORD)li.QuadPart;
bytesToRead = (fileSize/g_bytesPerPhysicalSector)*g_bytesPerPhysicalSector;
buffer = static_cast<char *>(VirtualAlloc(0, bytesToRead, MEM_COMMIT, PAGE_READWRITE));
OVERLAPPED overlapped;
ZeroMemory(&overlapped, sizeof(overlapped));
OVERLAPPED * lpOverlapped = &overlapped;
success = ReadFile(handle, buffer, bytesToRead, &bytesRead, lpOverlapped);
if(!success && GetLastError() != ERROR_IO_PENDING){
fprintf(stdout, "\n Error occured: %d", GetLastError());
fprintf(stdout, "\n reading file %s",filePathName);
CloseHandle(handle);
continue;
}
else
handleMap[handle] = overlapped;
}
// Status check and bytes Read value
for(std::map<HANDLE, OVERLAPPED>::iterator iter = handleMap.begin(); iter != handleMap.end(); iter++)
{
HANDLE handle = iter->first;
OVERLAPPED * overlappedPtr = &(iter->second);
success = GetOverlappedResult(handle, overlappedPtr, &bytesRead, TRUE);
if(success)
{
/* bytesRead value in some cases is unexpectedly zero */
/* no file is of size zero or lesser than 512 bytes(physical volume sector size) */
totalBytesRead += bytesRead;
CloseHandle(handle);
}
}
return totalBytesRead;
}
FILE_FLAG_NO_BUFFERING がない場合、totalBytesRead 値は 57 MB です。フラグが存在する場合、totalBytesRead の値は 57 MB よりもはるかに低く、2 MB から 15 MB のコードを実行するたびに変化し続けます。