web-dev-qa-db-ja.com

C ++での子プロセスのステータスの確認

fork()を使用して子プロセスを作成するプログラムがあります。 wait()を使用して子プロセスが終了するのを待ってから閉じるさまざまな例を見てきましたが、ファイルプロセスがまだ実行されているかどうかを簡単に確認するために何ができるのでしょうか。

私は基本的に無限ループを持っており、次のようなことをしたいと思っています。

if(child process has ended) break;

どうすればこれを行うことができますか?

14
Alex

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
}
35
Erik

EDIT:子プロセスの実行が停止したかどうかを知りたいだけの場合は、他の答えの方がおそらく良いでしょう。私は、プロセスが必ずしも終了することなく、複数の計算を実行できる場合の同期と関係があります。

子の計算を表すオブジェクトがある場合は、bool isFinished()などのメソッドを追加します。これは、子が終了した場合にtrueを返します。操作が終了したかどうかを表すプライベートboolメンバーをオブジェクトに含めます。最後に、子プロセスが計算の終了時に呼び出すのと同じオブジェクトに、別のメソッドprivate setFinished(bool)を設定します。

ここで最も重要なことはミューテックスロックです。 bool isFinished()およびsetFinished(bool)メソッド内を含め、メンバーにアクセスしようとするたびにロックするオブジェクトごとのミューテックスがあることを確認してください。

EDIT2:(いくつかのOO説明)

これをOOでどのように行うことができるかを説明するように求められたので、いくつかの提案をしますが、それは全体的な問題に大きく依存します。これを塩の山と一緒に取ってください。ほとんどのプログラムをCスタイルで記述し、1つのオブジェクトを浮かせておくと一貫性がなくなります。

簡単な例として、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
}

今あなたがフォークするあなたのメインプログラムで:

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;
}

それが理にかなっていることを願っています。

繰り返しますが、私が上に書いたのはCとC++の醜い融合(構文ではなくスタイル/ design)であり、コンテキスト内でOOとの同期を垣間見ることができます。

SIGCHLDシグナルを受け取るまで、子を待つ必要はありません。そのシグナルを受け取ったら、waitを呼び出して、それが探している子プロセスであるかどうかを確認できます。信号を受信して​​いない場合、子供はまだ走っています。

明らかに、子が終了するまで何もする必要がない場合は、waitを呼び出すだけです。

1
Gabe