Проверка состояния дочернего процесса в C++

у меня есть программа, которая использует fork() для создания дочернего процесса. Я видел различные примеры, которые используют wait() дождаться завершения дочернего процесса перед закрытием, но мне интересно, что я могу сделать, чтобы просто проверить, работает ли файловый процесс.

Я в принципе бесконечный цикл и я хочу сделать что-то вроде:

if(child process has ended) break;

как я мог это сделать?

3 ответов


использовать waitpid() С .

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

EDIT: если вы просто хотите знать, остановился ли дочерний процесс, то другие ответы, вероятно, лучше. Моя больше связана с синхронизацией, когда процесс может выполнять несколько вычислений, не обязательно завершаясь.

если у вас есть какой-то объект, представляющий дочернее вычисление, добавьте такой метод, как bool isFinished() который вернет true, если ребенок закончил. Член частная bool в объект, который представляет ли операция законченный. Наконец, есть еще один метод private setFinished(bool) на том же объекте, который вызывает ваш дочерний процесс, когда он завершает свои вычисления.

теперь самое главное-это mutex locks. Убедитесь, что у вас есть мьютекс для каждого объекта, который вы блокируете каждый раз, когда пытаетесь получить доступ к любым членам, в том числе внутри bool isFinished() и setFinished(bool) методы.

EDIT2: (некоторые пояснения ОО)

так как меня попросили объяснить, как это может быть сделано с OO, я дам несколько предложений, хотя это сильно зависит от общей проблемы, так что возьмите это с насыпью соли. Имея большую часть программы, написанной в стиле C, с одним объектом, плавающим вокруг, непоследовательно.

в качестве простого примера вы можете иметь класс под названием 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++ (не с точки зрения синтаксиса, а стиля/дизайна), и просто там, чтобы дать вам представление о синхронизации с OO, в вашем контексте.


вам не нужно ждать ребенка, пока вы не получите SIGCHLD сигнал. Если вы получили этот сигнал, вы можете позвонить wait и посмотреть, если это дочерний процесс, который вы ищете. Если вы не получили сигнал, ребенок все еще бежит.

очевидно, если вам не нужно ничего делать unitl ребенок заканчивает, просто позвоните wait.