2

在此处使用 SO 帖子:如何在 C++ 中读取 system() 调用的结果?

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

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;
}

我一直将它用于“立即”产生值的系统命令。我的问题是,如果 cmd 需要一些时间来运行,比如一分钟,然后写入结果,这个函数是否也可以工作。我在用 Python 做类似的事情时遇到了问题pexpect;如果 cmd 需要一段时间,则在等待结果时超时,并且我无法限制 cmd 的运行时间。我相信这个问题可以简化为 cmd 是否总是eof在运行多长时间后写入?

4

2 回答 2

3

feof() 未检测到输入流中的 EOF 字符。它指示是否在文件末尾尝试读取。此外,根据我的经验,我会说大多数命令不会在其输出末尾写入 EOF 字符。fread() 调用将阻塞,直到有数据要读取,除非它被中断,所以命令运行多长时间并不重要。根据您使用的操作系统,您可以告诉系统在出现信号时恢复中断的系统调用。我也同意 Bastile 的观点。您应该使用更大的缓冲区来提高 I/O 的效率。

于 2013-11-05T19:07:20.277 回答
2

除非该功能被中断,否则它将按您的预期运行。顺便说一句,你buf很小(只有 128 个字节)。我建议 4 或 8 KB(参见getconf(1) with 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 ... 如果您想从同一个进程读取和写入,您可能需要在创建pipe(2) -s.... 等之后使用poll(2)进行多路复用。 .

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

另请参阅fread(3)

于 2013-11-05T18:55:21.523 回答