2014-02-13 49 views
0

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

我是OSX/unix-like api的新手,但我可以理解做这样的事情的规范方式是分叉和管道stdouts在一起。不过,我不希望它重定向到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,似乎某种叉/ EXEC组合是不可避免的。现在的问题是,我的过程是非常大的并分叉它真的看起来是一个坏主意(我看到,如果父进程占用系统RAM的50%以上,一些unix实现不能这样做)。

我不能以任何方式避免此计划吗?我发现vfork()可能是一个可能的竞争者,所以也许我可以尝试使用vfork来模仿popen()函数。但是,大多数手册页声明,vfork可能只是fork()

+0

也许它应该注意到它只是伪代码。 exec应该执行命令行。 – Shaggi

回答

0

你有一个库调用来做到这一点:popen。它将为您提供文件描述符的返回值,并且您可以将该描述符读取到eof。它是stdio的一部分,所以你可以在OSX上做到这一点,但也可以在其他系统上做到这一点。请记住pclose()描述符。

#include <stdio.h> 

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

    int pclose(FILE *stream); 
如果你想保持输出,绝对没有重定向

,我们能想到的唯一的事情就是使用类似“三通” - 其将输出到文件,但维护它自己的标准输出的命令。在代码中实现它也相当容易,但在这种情况下可能不需要。

+0

这看起来很完美。有两个问题,当我到达EOF时,我认为这个过程终止了?其次,linux手册页声明它是一个fork包装 - 这会对性能产生巨大影响(例如,我的代码位于一个巨大进程内的动态库中) – Shaggi

+0

要在UNIX系统中创建进程, *在OS X上使用fork()/ execv()(或posix_spawn,几乎相同的东西)。但是,除非您反复使用数十次,否则不会有太大的性能影响。至于EOF,yes - pclose()也会等待进程结束,并返回它的返回值(即它退出())。 – Technologeeks

+0

好吧,但这是我要去的东西..这个想法当然是让主程序能够访问运行shell命令和程序,并且它有时会连续执行并作为循环的一部分例行程序也许是每分钟几次......并且我们可以假定主机进程占用大部分系统资源 – Shaggi