C ++管道系统调用总是以EOF结束吗?

时间:2013-11-05 18:51:06

标签: c++

在此处使用SO帖子:How do I read the results of a system() call in C++?

我能够编写一个运行任意系统命令的函数,并以字符串形式返回任何输出:

string pipeAndGetResults(string cmd)
{
    const char* ccmd = cmd.c_str();
    FILE* stream = popen( ccmd, "r" );
    std::ostringstream output;
    while( !feof( stream ) && !ferror( stream ))
    {
        char buf[128];
        int bytesRead = fread( buf, 1, 128, stream );
        output.write( buf, bytesRead );
    }
    string result = output.str();
    boost::trim(result);
    return result;
}

我总是将它用于系统命令,即时#34;产生价值。我的问题是,如果cmd需要一些时间来运行(例如一分钟),然后写入结果,此函数是否也会起作用。我在使用Python pexpect做类似的事情时遇到了问题。如果cmd需要一段时间,那么在等待结果时超时,我无法限制cmd的运行时间。我相信这个问题简化了cmd是否总是在经过多长时间后写eof

2 个答案:

答案 0 :(得分:3)

feof()未检测到输入流中的EOF字符。它指示是否尝试超过文件末尾的读取。另外,根据我的经验,我会说大多数命令不会在输出结尾处写一个EOF字符。 fread()调用将阻塞,直到有数据要读取,除非它被中断,因此命令运行的时间无关紧要。根据您使用的操作系统,您可以告诉系统在发出信号时恢复中断的系统调用。我也同意巴斯蒂利亚。您应该使用更大的缓冲区来提高I / O效率。

答案 1 :(得分:2)

除非该函数被中断,否则它将按预期运行。 BTW你buf非常小(只有128字节)。我会建议4或8千字节(请getconf(1)PIPE_BUF):

while( !feof( stream ) && !ferror( stream ))
{
    char buf[4096];
    memset (buf, 0, sizeof(buf)); //probably useless
    int bytesRead = fread(buf, 1, sizeof(buf), stream);
    if (bytesRead < 0) 
       break;
    output.write(buf,bytesRead);
}

另请阅读Advanced Linux Programming ...如果您想要从同一过程中读取和写入,您可能需要多路复用,例如在创建poll(2) - s ....等等之后使用pipe(2)

bufmemset的归零可能并非真正需要;但是,如果上述程序存在错误,它将使其更具可重复性。这就是我喜欢归零内存的原因。这里将内存归零比读取内存要快得多。

另见fread(3)