我正在帮助我的一个朋友用C ++实现软件,该软件利用了应该在单核上准并行运行的四个进程。
通过使用fork()
函数创建四个进程中的三个。这些过程由三个信号量(semaOne
,semaTwo
和semaThree
进行同步,并在无穷循环(proc1-> proc2-> proc3- > proc1-> ...)。第四个进程(显然是父进程)是看门狗进程,它执行自己的无限循环并观察三个子进程。
考虑孩子的功能正常,信号量和同步。
看门狗实现非常原始,但是足够了。孩子们使用其PID向看门狗注册自己,现在不得不不时tick
一次看门狗,并以此来增加计数器。当调度程序允许其运行时,看门狗本身会checks
子项的输入并减少每个已注册子项的计数器。如果任何计数器的状态为0,则看门狗应该采取措施。
问题是,有时当我们启动软件时,看门狗进程会在无休止的循环中调用check
函数,从而获得主动权并无限地运行,并且似乎被调度程序忽略,这样孩子们永远不会跑。经过几次尝试启动该软件,我们很幸运,孩子们设法开始了他们的“接力赛”,然后一切正常。
据我所知,调度程序正在循环模式下工作,应该在所有进程之间分配CPU资源,但这似乎无法正常工作。
请根据需要询问其他信息!
P.S。环境是在Virtual Box中运行的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;
}
}
我们要实现的目标如下:调度程序为子进程分配了运行时间,即使看门狗/父进程在启动时就进入了循环。
答案 0 :(得分:0)
谢谢2785528,这个想法可以检查调度程序类型!
我找到了解决方案,现在一切都按预期运行。
以下说明适用于我的开发系统Ubuntu 16.04,也适用于其他发行版。
在Linux Shell中,可以使用chrt
工具显示任何进程的调度策略。 -p
参数传递您要显示其调度策略的进程的PID。
以下输出适用于当前在我的系统上运行的Firefox:
$ chrt -p 19580
pid 19580's current scheduling policy: SCHED_OTHER
pid 19580's current scheduling priority: 0
“ SCHED_NORMAL / SCHED_OTHER
这是默认策略,对于具有某些交互作用的普通程序而言。会抢占其他进程。”
(来自http://manpages.ubuntu.com/manpages/xenial/man8/schedtool.8.html)
默认调度策略不是Rount-Robin!因此,要使用Round-Robin调度程序运行任何软件,必须对其进行明确选择。我的Ubuntu 16.04上有一个名为schedtool
的工具,可让您选择系统上可用的任何调度程序。
schedtool
(如果尚未安装)可以很容易地安装:
$ sudo apt-get install schedtool
现在,通过不带任何参数执行schedtool
,可以显示工具的帮助。以下是该工具可以处理的调度策略列表的摘录:
set scheduling policies:
-N for SCHED_NORMAL
-F -p PRIO for SCHED_FIFO only as root
-R -p PRIO for SCHED_RR only as root
-B for SCHED_BATCH
-I -p PRIO for SCHED_ISO
-D for SCHED_IDLEPRIO
由于我需要从Eclipse IDE开始运行的Round-Robin软件,因此我使用schedtool
使用Round-Robin调度程序启动Eclipse,并将进程的优先级设置为20:
$ sudo schedtool -R -p 20 -e eclipse
现在,将从IDE启动的所有进程也将通过Round-Robin Scheduler启动。