按照主題我試圖開發一個簡單的管道父/子程序。 該程序的主要目的是保持子進程的活動,並使用std::cin
和std::cout
在父進程/子進程之間進行通信。Windows:如何讓子進程讀取輸入匿名管道而不關閉它?
在Linux上,所有這些工作都很好。
在Windows上我一直在下面的例子中here,並有一個與Linux的一個奇特的差別:一個具有調用
CloseHandle(g_hChildStd_IN_Wr)
要寫入孩子管沖洗掉。這有關閉管道的副作用,因此將我的連接終止到子進程。
我也試過使用FlushFileBuffers,但它不起作用。
任何想法我怎麼能刷新緩衝區而不必關閉匿名管?
以下兩種來源父和子過程。
如果父過程的代碼基本上是一個在上面的例子:
// IN_Wr_ is initialized as below with bInheritHandle=TRUE
::CreatePipe(&IN_Rd_, &IN_Wr_, &saAttr, 0);
// and
::SetHandleInformation(IN_Wr_, HANDLE_FLAG_INHERIT, 0)
// When I spawn the child process I do
STARTUPINFO siStartInfo = {0};
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = INVALID_HANDLE_VALUE;
siStartInfo.hStdOutput = OUT_Wr_;
siStartInfo.hStdInput = IN_Rd_;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
...
// then in order to write to std::cin
const DWORD reqSz = static_cast<DWORD>(std::strlen(request));
DWORD written = 0;
while(true) {
DWORD curWritten = 0;
if(!WriteFile(IN_Wr_, request + written, reqSz-written, &curWritten, NULL))
throw std::runtime_error("Error on WriteFile");
written += curWritten;
if(written == reqSz) {
// all written, done
break;
}
}
::FlushFileBuffers(IN_Wr_);
// only when I do this CloseHandle then the child process
// is able to read data
::CloseHandle(IN_Wr_);
此孩子代碼是一個簡單回聲服務器,沿着線:
buif[2048+1];
while(std::cin) {
std::cin.read(buf, 2048);
const auto rb = std::cin.gcount();
buf[rb] = '\0';
std::cout << buf << std::endl; // this does flush
}
好吧,首先,linux沒有那個MSDN函數:'CloseHandle()'。然後使用語法::'fflush(FILE * stream);' – user3629249
可以刷新任何輸出流。無需任何操作*來刷新管道。該示例專門關閉句柄以通知孩子它已完成,而不是因爲孩子不能讀取數據。 (如果你使用運行時庫例程,顯然你需要刷新這些緩衝區,但是你不需要在操作系統級別做任何事情。) –
@HarryJohnston沒有*關閉*管道,子進程*塊*在Windows上無限期地在該流('std :: cin')上進行測試(在Windows 7上測試)。嘗試發送〜10個字節。發生什麼事是那些保持緩衝,直到或緩衝區已滿或*刷新*。唉'FlushFileBuffers'不起作用,因此唯一的辦法就是'CloseHandle'。其中*強制*沖洗*,但也關閉了溝通渠道。 – Emanuele