Ответ 1
Используйте 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
}
У меня есть программа, которая использует fork()
для создания дочернего процесса. Я видел различные примеры, которые используют wait()
для ожидания завершения дочернего процесса до закрытия, но мне интересно, что я могу сделать, чтобы просто проверить, все ли работает процесс файла.
У меня в основном есть бесконечный цикл, и я хочу сделать что-то вроде:
if(child process has ended) break;
Как я могу это сделать?
Используйте 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
}
РЕДАКТИРОВАТЬ: Если вы просто хотите узнать, остановлен ли дочерний процесс, другие ответы, вероятно, лучше. Mine больше связан с синхронизацией, когда процесс может выполнять несколько вычислений, не обязательно заканчивая.
Если у вас есть объект, представляющий детское вычисление, добавьте метод, например bool isFinished()
, который вернет true, если ребенок закончил. У вас есть частный член bool в объекте, который показывает, завершилась ли операция. Наконец, используйте другой метод private setFinished(bool)
на том же объекте, что и ваш дочерний процесс, когда он заканчивает вычисление.
Теперь самое важное - блокировки мьютексов. Удостоверьтесь, что у вас есть мьютекс для каждого объекта, который вы блокируете каждый раз при попытке доступа к любым членам, в том числе внутри методов bool isFinished()
и setFinished(bool)
.
EDIT2: (некоторые разъяснения OO)
Поскольку меня попросили объяснить, как это можно сделать с OO, я дам несколько предложений, хотя это сильно зависит от общей проблемы, поэтому возьмите это с кучей соли. Наличие большей части программы, написанной в стиле C, с одним объектом, плавающим вокруг, является непоследовательным.
В качестве простого примера вы можете иметь класс под названием ChildComputation
class ChildComputation {
public:
//constructor
ChildComputation(/*some params to differentiate each child 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
}
Теперь в вашей основной программе, где вы используете fork:
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 и С++ (не в терминах синтаксиса, а стиля/дизайна), и именно здесь, чтобы дать вам представление о синхронизации с OO, в вашем контексте.
Вам не нужно ждать ребенка, пока не получите сигнал SIGCHLD
. Если вы получили этот сигнал, вы можете вызвать wait
и посмотреть, является ли он процессом, который вы ищете. Если вы еще не получили сигнал, ребенок все еще работает.
Очевидно, что если вам нужно ничего не сделать, чтобы ребенок закончил, просто позвоните wait
.