C用于任务切换的信号计时器

时间:2018-12-28 12:57:02

标签: c multithreading timer signals

我正在构建一个简单的任务切换器,该切换器可以循环运行两个功能。这个想法是,它将f1运行一段时间,然后将f2的控制权赋予同一amout,然后以无限循环的方式控制f1,f2。

问题在于,每当我运行该程序时,第一个开关运行良好,但随后的开关永远不会发生。卡在f2中。

我尝试了其他实现方式,最多归档3个开关(此后程序被冻结)。

这是我当前的实现方式:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

int count = 0;
int flag  = 0;

void f1() {
    for (;;) printf("A");
}

void f2() {
    for (;;) printf("B");
}

void sched() {
    flag = !flag;
    if (flag)
        f1();
    else
        f2();
}

void sighandler(int signo)
{
 printf("signal %d occurred %d times\n",signo, ++count);
 sched();
}

int main(void)
{
 struct itimerval it;
 struct sigaction act, oact;
 act.sa_handler = sighandler;
 sigemptyset(&act.sa_mask);
 act.sa_flags = 0;

 sigaction(SIGPROF, &act, &oact); 

 it.it_interval.tv_sec = 0;
 it.it_interval.tv_usec = 10000;
 it.it_value.tv_sec = 0;
 it.it_value.tv_usec = 10000;
 setitimer(ITIMER_PROF, &it, NULL);

 sched();
}

任何建议将不胜感激。

2 个答案:

答案 0 :(得分:3)

您的信号处理程序调用{​​{1}},它从不返回(但最终在sched()循环中的任何一个中结束)。因此,在第一次切换之后,您始终位于信号处理程序中,并且进一步屏蔽了信号。

答案 1 :(得分:0)

尽管您已经得到了很好的回答

  

您的信号处理程序调用sched(),它永远不会返回(但最终会出现在for(;;)中的任何一个...

多任务实现的问题在于,要使任务切换器正常工作,您需要进行上下文切换。上下文切换器是一个例程,直到完成所有上下文切换到其他进程并且要调度的下一个任务是要返回的任务,它才会返回。是致电的王者

yield();

,但实际上下文切换发生在yield的内部中。上下文切换是不能实现为简单例程(某些代码您调用并返回)的东西,因为它会在另一个上下文中返回。为此,您需要调用yield(),并且yield的代码必须将所有cpu寄存器更改为它们在 other 上下文中具有的值(包括堆栈指针),因此要进行约会则需要两个堆栈),然后继续执行该代码(这将使程序在另一个上下文中返回

因此,您需要在某个地方存储将允许并行运行的所有任务的上下文。这包括cpu状态和任务堆栈。然后,您需要一个例程(这是实际的上下文切换),该例程将旧上下文(cpu正在使用的上下文)存储在保存存储中,并调出(并安装)要计划的新任务的上下文。像这样:

void task_switch(struct context *old_ctx, struct context *new_ctx);

并且此例程必须用汇编器编写。...它必须进行上下文切换,其中包括切换每个任务的堆栈。

您现在怎么看?