c - Windows重叠IO实际上是阻塞的

标签 c windows winapi overlapped-io

我正在尝试 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调用。

我尝试将 malloc 替换为 VirtualAlloc,将 ReadFileEx 替换为 ReadFile,添加 FILE_FLAG_NO_BUFFERING,并检查读取后 ReadFile 的返回值为 0,并且 GetLastError 将为 ERROR_IO_PENDING。我尝试使用 RAMMap 来查看文件是否在缓存中,但只有 96KB 存在。

我运行的是带有 8GB RAM 的 Windows 10(版本 1703)。

最佳答案

好的,我已经成功了,这一切都归功于@RbMm。

内存分配没有改变任何东西,但 FILE_FLAG_NO_BUFFERING 标志和 ReadFile 的使用使其工作。我尝试在 ReadFileEx 之后使用 SleepEx,它在 0 处引发了访问冲突,这证明了 @RbMm 的观点,即 lpCompletionRoutine 不是可选的,但强制的。 (对我来说,这意味着我将使用 ReadFile 因为我不需要完成例程)

至于为什么我花了这么长时间才意识到发生了什么:我太信任调试器了,显然闯入调试器并没有停止 IO 进程,这意味着内存仍在OVERLAPPED<内更新 结构,这让我觉得事情是瞬时的。最重要的是,我期望 ReadFile 能够快速返回,但如果我尝试读取 512MB,实际上需要 20 毫秒,当我请求较小的量时,速度要快得多。

谢谢大家的建议:)

为了完整起见,这是工作程序:

  const DWORD Size = 1<<20;
  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_FLAG_NO_BUFFERING|FILE_FLAG_OVERLAPPED, NULL);
  assert(File!=INVALID_HANDLE_VALUE);
  DWORD Result = ReadFile(File, Buffer, Size, NULL, &Overlapped);
  assert(Result==FALSE && GetLastError()==ERROR_IO_PENDING);
  while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) {
    printf("Waiting...\n");
  }

关于c - Windows重叠IO实际上是阻塞的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43956446/

相关文章:

c - 为什么这个缓冲区指向不可寻址的字节?

c - popen 与 C 中的系统函数

在 Linux 中播放音频文件的 C 程序最后会出现噼啪声

.net - 如何设置amcap的默认色彩空间为YUY2?

c - C 中的正则表达式

ruby-on-rails - Ruby 尝试从 https ://api. ruby​​gems.org 下载,即使使用源 key

c++ - 如何轻松检测字符串中的utf8编码?

windows - 与 docker 容器共享 windows 文件夹(c/Users/除外)(使用 docker windows 客户端)

c++ - 主窗口中的列表框

winapi - 给定 HWND,如何从所有者绘制的窗口中提取文本信息?