pclose()
的手册页说:
我觉得这意味着如果 FILE*
创建的关联 popen()
以 "r"
类型打开以读取 command
的输出,那么在调用 pclose()
之前,您不确定输出是否已完成。但是在 pclose()
之后,关闭的 FILE*
肯定是无效的,所以你怎么能确定你已经阅读了 command
的整个输出?
为了通过示例说明我的问题,请考虑以下代码:
// main.cpp
#include <iostream>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
int main( int argc, char* argv[] )
{
FILE* fp = popen( "someExecutableThatTakesALongTime", "r" );
if ( ! fp )
{
std::cout << "popen failed: " << errno << " " << strerror( errno )
<< std::endl;
return 1;
}
char buf[512] = { 0 };
fread( buf, sizeof buf, 1, fp );
std::cout << buf << std::endl;
// If we're only certain the output-producing process has terminated after the
// following pclose(), how do we know the content retrieved above with fread()
// is complete?
int r = pclose( fp );
// But if we wait until after the above pclose(), fp is invalid, so
// there's nowhere from which we could retrieve the command's output anymore,
// right?
std::cout << "exit status: " << WEXITSTATUS( r ) << std::endl;
return 0;
}
我的问题,如上面的内联:如果我们只确定输出生成子进程在
pclose()
之后终止,我们怎么知道用 fread()
检索的内容是完整的?但是如果我们等到 pclose()
之后, fp
是无效的,所以我们再也无法检索命令的输出了,对吧?这感觉就像一个先有鸡还是先有蛋的问题,但我已经看到了与上述类似的代码,所以我可能误解了一些东西。我很感激对此的解释。
最佳答案
TL;DR 执行摘要:我们如何知道使用 fread() 检索的内容是否完整? — 我们有一个 EOF。
当子进程关闭管道的末端时,您会得到一个 EOF。当它显式调用 close
或退出时可能会发生这种情况。在那之后,你的管道末端不会有任何东西出来。获得 EOF 后,您不知道进程是否已终止,但您确实知道它永远不会向管道写入任何内容。
通过调用 pclose
关闭管道的末端并等待子进程的终止。当 pclose
返回时,您知道子进程已终止。
如果您在没有获得 EOF 的情况下调用 pclose
,并且 child 尝试将内容写入管道的末端,它将失败(实际上它将获得 SIGPIPE
并且可能会死)。
这里绝对没有任何鸡和蛋的情况。
关于c++ - 在 pclose() 之前从 popen()ed FILE* 读取的输出是否完成?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52211756/