【问题标题】:Cant write to Windows pipe via stdout无法通过标准输出写入 Windows 管道
【发布时间】:2018-10-10 21:08:26
【问题描述】:

_open_osfhandle 从 Windows 文件句柄创建 C 文件描述符,_dup 可以更改现有 fd 的底层文件对象。当用于将stdout 重定向到CreatePipe 管道时,ReadFile 不会捕获写入stdout 的输出。

以下代码 sn-p 演示了我正在尝试的核心。 我想创建一个匿名管道,替换 stdout 以便我可以从读取句柄中读取它。

我能够找到的文档表明_open_osfhandle_dup2 可以执行此诡计,并且dup2 的Microsoft 文档页面特别呼吁尽可能替换stdout 中的fd。

考虑到这一切,我希望下面的代码会立即从 ReadFile 返回,其中包含 printf 写入的字节,因为之前对 _writefprintf 的调用按预期工作。

HANDLE hread;
HANDLE hwrite;
SECURITY_ATTRIBUTES sa = { sizeof(sa),NULL,TRUE };
CreatePipe(&hread, &hwrite, &sa, 0);
int fd = _open_osfhandle(intptr_t(hwrite), _O_TEXT);
FILE *fp = _fdopen(fd, "w");
setvbuf(fp, NULL, _IONBF, 0);
_dup2(_fileno(fp), _fileno(stdout));
TCHAR buffer[64] = { 0 };
DWORD bytesRead;
//_write(fd, "_write", 6); // works
//fprintf(fp, "fprintf"); // works
printf("printf");
ReadFile(hread, buffer, sizeof(buffer), &bytesRead, NULL);

【问题讨论】:

  • 在什么问题?可能 fprintf 在内部缓冲区中缓存数据,而不是调用 WriteFile。直到您不刷新缓冲区,管道中才会没有数据。在 fprintf 之后调用 fflush
  • 这就是我遇到的问题。直到我发现setvbuf。最终目标是使用 _dup2 替换标准输出中的 fd。但这仍然行不通。

标签: winapi visual-c++ pipe stdio


【解决方案1】:

调查终于有了成果。默认情况下,_fdopen 打开的文件流被缓冲,以防止任何实际写入底层 OS 管道句柄。 setvbuf 可用于将其关闭,以便立即进行写入。

执行dup2 重置绑定到标准输出文件描述符的底层文件会重置缓冲,因此以下代码有效。对_fdopen 的调用在不需要时被丢弃,并在标准输出上执行`setvbuf'。

HANDLE hread;
HANDLE hwrite;
SECURITY_ATTRIBUTES sa = { sizeof(sa),NULL,TRUE };
CreatePipe(&hread, &hwrite, &sa, 0);
int fd = _open_osfhandle(intptr_t(hwrite), _O_TEXT);
_dup2(fd, _fileno(stdout));
setvbuf(stdout, NULL, _IONBF, 0);
TCHAR buffer[64] = { 0 };
DWORD bytesRead;
printf("printf");
ReadFile(hread, buffer, sizeof(buffer), &bytesRead, NULL);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-05
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
  • 1970-01-01
相关资源
最近更新 更多