具有重叠I/O的FILE_FLAG_NO_BUFFERING-字节读取为零

FILE_FLAG_NO_BUFFERING with overlapped I/O - bytes read zero

本文关键字:NO FLAG BUFFERING- 读取 字节 FILE 重叠      更新时间:2023-10-16

在使用具有重叠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。

当文件大小小于g_bytesPerPhysicalSector时,您对bytesToRead的计算将产生0。因此,对于小文件,您请求的是0字节。