从stdin读取的Win32缓冲区大小

时间:2019-08-21 10:09:26

标签: windows winapi stdin

我正在尝试从Windows上的C ++有效地从stdin读取数据,这意味着最好是大块。这可以通过以下方式完成:

ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, bytestoread, &bytesread, 0);

read(0, buf, bytestoread);

但是在两种情况下,只有将bytestoread设置为非常小的数字(例如, 50;如果设置为更大的数字,例如1兆字节时,调用失败并显示“没有足够的空间”错误,好像数据没有直接进入我提供的缓冲区,而是通过某个固定大小的内部缓冲区复制了。无论输入是通过管道传输还是在控制台上键入,都是如此。

Windows是否仅限制一次可以从stdin读取的进程有多大?如果是这样,保证工作的最大块大小是多少?

显示问题的完整程序:

    #include <errno.h>
    #include <io.h>
    #include <stdio.h>
    #include <string.h>

    char buf[1000000];

    int main(int argc, char **argv) {
      auto r = read(0, buf, sizeof buf);
      if (r < 0)
        perror("read");
      return 0;
    }

3 个答案:

答案 0 :(得分:1)

您没有说要使用哪个版本的运行时和操作系统,但是我无法在Windows 10上使用MSVC 19.16.27031.1重现此问题。有一些已记录的原因可能会导致故障。从MSDN documentation of ReadFile:

  

可以使用带有控制台输入句柄的ReadFile从控制台输入缓冲区读取字符。控制台模式确定ReadFile函数的确切行为。默认情况下,控制台模式为ENABLE_LINE_INPUT,它指示ReadFile应该读到到达回车符为止。如果按Ctrl + C,则呼叫成功,但是GetLastError返回ERROR_OPERATION_ABORTED。有关更多信息,请参见CreateFile

还有另一种方式可以获取与异步I / O相关的错误,但这似乎不是问题所在。您可能想用SetConsoleMode关闭ENABLE_LINE_INPUT标志。该文档还说,如果无法锁定缓冲区的内存页,则调用可能会失败,ERROR_NOT_ENOUGH_QUOTA失败。但是,您使用的静态缓冲区应该不会出现此问题。

如果您正在读取磁盘上的文件,而不是控制台流,那么您可以map it to memory,通过与虚拟内存相同的机制来消除任何中间缓冲并根据需要加载文件的各个部分。

答案 1 :(得分:1)

如果您尝试读取标准输入 binary 数据,您需要:

  1. 设置_setmode( _fileno( stdin), _O_BINARY);
  2. fread( buf, 1, bufSize, stdin)

看看我的类似解决方案,当 应用程序通过 stdin、油门速度和 把它发给stdout

bin_pipe_throttle

答案 2 :(得分:0)

据我所知,stdin不受限制。它可以作为无休止的Stream,可以提供所需的存储量。我看到的唯一选择是,您正在使用的内核有时会阻塞

相关问题