【问题标题】:does a C++ piped system call always end with EOF?C++ 管道系统调用是否总是以 EOF 结尾?
【发布时间】:2013-11-05 18:51:06
【问题描述】:

在此处使用 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;
}

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

【问题讨论】:

    标签: c++


    【解决方案1】:

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

    【讨论】:

    • 通常(在 x86 上)charunsignedEOF 是 -1 所以甚至不能是 char
    • 特别是,EOF 不是流的一部分,而只是标准 C 函数 getchar() 返回的非字符整数,表示流已结束。管道不能结束,除非操作系统非常确定不会再写入更多的输出,这不早于输出被管道的程序终止,或者程序明确地关闭了它的标准输出流。
    • 假设我将“128”替换为“4096”,我该如何处理fread 中的1?
    • 1 可以留下来。这意味着读取 1 条记录。将 128 更改为 4096 或 sizeof(buf) 告诉它读取 最多 4096 字节的 1 条记录。
    【解决方案2】:

    除非该功能被中断,否则它将按您的预期运行。顺便说一句,buf 非常小(只有 128 个字节)。我建议 4 或 8 KB(参见 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);
    }
    

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

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

    另见fread(3)

    【讨论】:

    • 我把它改成了buf[4096],然后改成了fread( buf, 1, 4096, stream ); 我也应该改那个1吗?那有什么作用?
    • 当然,把大小和参数改成fread;你的 128 应该是 sizeof(buf) 对于 fread ...
    • 嗯。为什么是memset?除非我弄错了,否则完全没有必要。
    猜你喜欢
    • 2011-08-29
    • 2013-02-11
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多