Проверка состояния дочернего процесса в 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
.