Проверка состояния дочернего процесса в C ++ - PullRequest
13 голосов
/ 12 марта 2011

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

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

if(child process has ended) break;

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

Ответы [ 3 ]

35 голосов
/ 12 марта 2011

Используйте 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
}
2 голосов
/ 12 марта 2011

РЕДАКТИРОВАТЬ: Если вы просто хотите узнать, прекратился ли дочерний процесс, тогда другие ответы, вероятно, лучше.Мой больше связан с синхронизацией, когда процесс может выполнить несколько вычислений, без обязательного завершения.

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

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

1 голос
/ 12 марта 2011

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

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

...