捕获子stdout到缓冲区

时间:2014-02-13 01:12:23

标签: c++ unix fork stdout child-process

我目前正在开发一个跨平台项目。在Windows上,我有一个运行进程/脚本(使用命令行)的类,等待它结束,并从stdout / stderr读取所有内容到缓冲区。然后我将输出打印到自定义“控制台”。注意:这不是将子标准输出重定向到父标准输出,只是从子标准输出到父标记的管道。

我是OSX / unix-like api的新手,但我可以理解做这样的事情的规范方式是分叉和管道标准。但是,我不想将它重定向到stdout,我想捕获输出..它应该像这样工作(伪代码,与unix函数完全相似的相似):

class program
{
    string name, cmdline;
    string output;
    program(char * name, char * cmdline)
        : name(name), cmdline(cmdline) {};

    int run()
    {
        // run program - spawn it as a new process
        int pid = exec(name, cmdline);
        // wait for it to finish
        wait(pid);
        char buf[size];
        int n;
        // read output of program's stdout
        // keep appending data until there's nothing left to read
        while (read(pid, buf, size, &n))
            output.append(buf, n);
        // return exit code of process
        return getexitcode(pid);
    }

    const string & getOutput() { return output;  }
};

我将如何在OSX上执行此操作?

E:

好吧所以我研究了相关的api,似乎某种fork / exec组合是不可避免的。手头的问题是我的进程非常大并且分叉它似乎是一个坏主意(我发现如果父进程占用系统的50%以上,某些unix实现无法做到这一点RAM)。

我不能以任何方式避免这个计划吗?我看到vfork()可能是一个可能的竞争者,所以也许我可以尝试使用vfork来模仿popen()函数。但话说回来,大多数手册都说vfork可能只是fork()

1 个答案:

答案 0 :(得分:0)

你有一个库调用来做到这一点:popen。它将为您提供文件描述符的返回值,您可以读取该描述符直到eof。它是stdio的一部分,因此您可以在OSX上执行此操作,但也可以在其他系统上执行此操作。只记得pclose()描述符。

 #include <stdio.h>

     FILE *     popen(const char *command, const char *mode);

     int    pclose(FILE *stream);

如果你想保持绝对没有重定向的输出,我们唯一能想到的是使用像“tee”这样的命令 - 一个将输出分成文件但保留自己的标准输出的命令。在代码中实现它也相当容易,但在这种情况下可能没有必要。