Я помогаю своему другу реализовать программное обеспечение на C ++, которое использует четыре процесса, которые должны выполнять квазипараллельно на одном ядре.
Три из четырех процессов создаются с использованиемfork()
-функция.Эти процессы синхронизируются тремя семафорами (semaOne
, semaTwo
и semaThree
) и запускают "эстафету" один за другим в бесконечном цикле (proc1 -> proc2 -> proc3 -> proc1 -> ...).Четвертый процесс (очевидно, родительский) - это сторожевой процесс, который выполняет свой собственный бесконечный цикл и наблюдает за тремя дочерними процессами.Представьте, что дети функционируют так, как ожидалось, семафоры и синхронизация тоже.
Реализация сторожевого таймера очень примитивна, но достаточна.Дети регистрируют себя в сторожевом таймере с помощью своего PID и теперь обязаны время от времени tick
сторожевым таймером увеличивать счетчик.Сам сторожевой таймер, когда он разрешен планировщиком, запускает checks
записи дочерних элементов и уменьшает счетчик каждого зарегистрированного дочернего элемента.Если какой-либо счетчик достигает состояния 0, сторожевой таймер должен принять меры.
Проблема заключается в том, что иногда, когда мы запускаем программное обеспечение, сторожевой таймер обрабатывает, где в бесконечном цикле это check
-функцияназывается, захватывает инициативу и работает бесконечно и, кажется, планировщик игнорирует ее, поэтому дети никогда не бегут.После нескольких попыток запустить программное обеспечение нам повезло, что детям удалось запустить свою «эстафету», и тогда все работает нормально.
Как я понимаю, планировщик работает в режиме циклического перебора и работаетпредполагается, что ресурсы процессора распределяются между всеми процессами, но, похоже, это не работает должным образом.
Пожалуйста, запросите дополнительную информацию, если это необходимо!
PS Среда, в которой работает Ubuntu Linux 16.04, работает вВиртуальный ящик
Как вы можете видеть, я уже пытался уменьшить приоритет родительского процесса в надежде, что это может повлиять на планировщик, и призвать его предоставить временной интервал для детей, но этого никогда не происходит..
// main.cpp
// Shared memory allocation and instantiation of semaphores happen here
// This part of the code relies on a simple framework that was given
// by the lecturer. It works as expected and is of no concern in the scope
// of the actual problem.
CWatchdog myWD;
pthread_t proc1 = 0;
pthread_t proc2 = 0;
pthread_t proc3 = 0;
int main(void) {
pthread_t PID;
myWD.init();
PID = fork();
if (PID == 0) {
// proc1
proc1 = getpid();
myWD.register(proc1);
while (true) {
semaOne->take();
std::cout << "[PROC 1] here" << std::endl;
// per1form proc1 task here and TICK the watchdog
myWD.tick(proc1);
usleep(2000000);
semaTwo->give();
}
} else if (fork() == 0) {
// proc2
proc2 = getpid();
myWD.register(proc2);
while (true) {
semaTwo->take();
std::cout << "[PROC 2] here" << std::endl;
// perform proc2 task here and TICK the watchdog
myWD.tick(proc2);
usleep(2000000);
semaThree->give();
}
} else if (fork() == 0) {
// proc3
proc3 = getpid();
myWD.register(proc3);
while (true) {
semaThree->take();
std::cout << "[PROC 3] here" << std::endl;
// perform proc3 task here and TICK the watchdog
myWD.tick(proc3);
usleep(2000000);
semaOne->give();
}
} else {
pthread_t wdProcID = getpid();
int myPrio = 0;
myPrio = getpriority(PRIO_PROCESS, 0);
// 0 for current process!
std::cout << "[WD] PID, priority (old) " << wdProcID << ", " << myPrio << std::endl;
setpriority(PRIO_PROCESS, 0, -20);
while (true) {
std::cout << "[WD] here" << std::endl;
// perform watchdog task here: CHECK the children
myWD.check();
usleep(50000);
}
return 0;
}
}
Мы хотим добиться следующего: планировщик предоставляет дочерним процессам свои временные интервалы для запуска, даже если сторожевой / родительский процесс входит в свой цикл при запуске рано.