2014-02-13 45 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