【发布时间】:2017-10-12 21:04:42
【问题描述】:
我正在尝试 Windows 重叠 IO,但我似乎无法让它异步工作。我已经编译并运行了下面的程序,但它从不打印任何东西,它只是默默地完成。我读过小读可能会同步,所以我特意选择读512MB。
const DWORD Size = 1<<29; // 512MB
char* Buffer = (char*)malloc(Size);
DWORD BytesRead;
OVERLAPPED Overlapped;
memset(&Overlapped, 0, sizeof(Overlapped));
HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
assert(File!=INVALID_HANDLE_VALUE);
DWORD Result = ReadFileEx(File, Buffer, Size, &Overlapped, NULL); // This line takes 150ms according to the debugger
assert(Result);
while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) {
printf("Waiting...\n");
}
作为附加信息,我已将代码单步执行到调试器中,Overlapped.InternalHigh 值在ReadFileEx 调用期间得到更新(与Size 具有相同的值)。
我尝试将malloc 替换为VirtualAlloc,将ReadFileEx 替换为ReadFile,添加FILE_FLAG_NO_BUFFERING,并检查ReadFile 的返回值为0,GetLastError 为ERROR_IO_PENDING读完之后。我尝试使用 RAMMap 来查看文件是否在缓存中,但其中只有 96KB。
我正在运行具有 8GB RAM 的 Windows 10(版本 1703)。
【问题讨论】:
-
也许文件被操作系统缓存了,所以操作系统决定它可以轻松地立即为读取服务?
-
@EOF 会严重缓存整个 512MB 以上的文件吗?另外,如果它被缓存,我的读取仍然需要 150 毫秒......那么如果它不能保证我快速返回,那么重叠的意义何在?
-
这确实与缓存相关。使用
FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING打开文件并分配PVOID Buffer = VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE)(必须对齐以进行非缓存读取)-并检查结果。在您的情况下,最好使用ReadFile(不带Ex)-在这种情况下,它会返回false,最后一个错误-ERROR_IO_PENDING -
我很确定如果有足够的 RAM 可用,它会缓存一个 512MB+ 的文件。您可以尝试在测试前使用 SysInternals RAMMap 清除缓存。
-
奇怪... 150 毫秒对于排队异步 IO 请求来说太长了,是的,我同意这是应该发生的:(
标签: c windows winapi overlapped-io