2011-03-11 22 views
13

我有一個程序使用fork()來創建子進程。我已經看到了各種使用wait()來等待子進程在關閉之前結束的例子,但是我想知道我能做些什麼來簡單地檢查文件進程是否仍在運行。在C++中檢查子進程的狀態

我基本上有一個無限循環,我想要做的事,如:

if(child process has ended) break;

我怎麼會去這樣做呢?

回答

33

使用waitpid()WNOHANG選項。

int status; 
pid_t result = waitpid(ChildPID, &status, WNOHANG); 
if (result == 0) { 
    // Child still alive 
} else if (result == -1) { 
    // Error 
} else { 
    // Child exited 
} 
+0

因此,ChildPID是我用來區分父母和孩子的結果,並且結果是一個新的pid_t,它使得一個新的子流程監視孩子退出? – Alex 2011-03-11 21:46:44

+0

不,ChildPID是'fork()'返回的子進程ID。 'waitpid()'只是一個返回一個值的函數:'0','ChildPid'或'-1' – Erik 2011-03-11 21:49:08

+0

嗯,我的意思是我做了一個'pid_t'來說'pid = fork()'。現在爲我的父母和孩子編寫代碼我有一個if-else檢查'if(pid)'來標識父進程,因爲在父進程中'pid'包含孩子的pid編號,並且在孩子'pid'中包含'0'。所以,如果我正確理解這一點,我相信我應該在你說過使用'ChildPID'的地方使用'pid'。 – Alex 2011-03-11 21:56:18

1

您不需要等待孩子,直到您得到SIGCHLD信號。如果您收到該信號,您可以致電wait並查看它是否是您要查找的子過程。如果你沒有收到信號,那孩子還在跑步。

很顯然,如果您不需要做任何事情,孩子就可以完成,只需撥打wait即可。

+3

我怎麼知道我是否得到了這個信號? – Alex 2011-03-11 21:43:28

2

編輯:如果你只是想知道子進程是否停止運行,那麼其他答案可能會更好。當一個進程可以進行多次計算而不一定終止時,我的工作就更多地與同步有關。

如果您有一些代表子計算的對象,請添加一個方法,如bool isFinished(),如果孩子已完成,則返回true。在表示操作是否完成的對象中有一個私有bool成員。最後,在子進程完成其計算所調用的同一對象上有另一個私有的方法setFinished(bool)

現在最重要的是互斥鎖。確保每次嘗試訪問任何成員時都鎖定每個對象的互斥鎖,包括在bool isFinished()setFinished(bool)方法中。

EDIT2:(一些OO澄清)

自從我被要求解釋這到底是怎麼用OO做,我給一些建議,雖然它很大程度上取決於整體的問題,所以帶上一堆鹽吧。使用C風格編寫的大部分程序都有一個浮動的對象是不一致的。

ChildComputation* myChild = new ChildComputation(/*params*/); 
ChildPID= fork(); 
if (ChildPID == 0) { 
    // will do the computation and automatically set its finish flag. 
    myChild->doComputation(); 
} 
else { 
    while (1) { // your infinite loop in the parent 
     // ... 

     // check if child completed its computation 
     if (myChild->isFinished()) { 
      break; 
     } 
    } 

    // at the end, make sure the child is no runnning, and dispose of the object 
    // when you don't need it. 
    wait(ChildPID); 
    delete myChild; 
} 

希望是有道理的:

舉個簡單的例子,你可以有一個類在你的主程序,在那裏你叉叫ChildComputation

class ChildComputation { 

    public: 
    //constructor 
    ChildComputation(/*some params to differentiate each child's computation*/) : 
     // populate internal members here { 
    } 
    ~ChildComputation(); 

    public: 
    bool isFinished() { 
     m_isFinished; // no need to lock mutex here, since we are not modifying data 
    } 

    void doComputation() { 
     // put code here for your child to execute 
     this->setFinished(true); 
    } 

    private: 
    void setFinished(bool finished) { 
     m_mutex.lock(); 
     m_isFinished = finished; 
     m_mutex.unlock(); 
    } 

    private: 
    // class members 
    mutex m_mutexLock; // replace mutex with whatever mutex you are working with 
    bool m_isFinished; 
    // other stuff needed for computation 
} 

現在。

要重申,上面我所編寫的是C的醜陋的合併和C++(在語法方面不大,但風格/設計),並且就在那裏給你OO同步一瞥,在你的上下文中。

+0

我不確定如何使我的子進程成爲一個對象。這是我第一次做這種編程,所以我的理解還是比較基礎的。現在我只有一個主函數,它創建兩個管道然後分叉,並且具有使用pid分隔父進程和子進程的代碼的if-else語句。我怎麼能讓這個面向對象? – Alex 2011-03-11 21:41:25

+0

如果你的問題很簡單,也許你甚至不需要做它OO,我只是假設它,因爲你把C++作爲標籤。這實際上取決於你想要解決的整體問題。 Erik的答案是最適合您當前的代碼。我會添加一些東西到我的答案澄清雖然。 – 2011-03-11 21:49:25

+0

這是有道理的。我認爲它確實比C++問題更像C問題。我習慣於使用C++,並且在程序中包含一些C++函數,但程序的這部分確實更像C語言。我想在將來我會將它標記爲C/C++。 – Alex 2011-03-11 22:21:46