我正在构建一个先发制人的用户空间线程调度程序,它使用计时器来中断线程并根据优先级在它们之间切换。但是,一旦线程中断,我似乎无法让它完成;只能重新开始。使用swapcontext我甚至可能要求什么?这段代码的结果应该允许itake5seconds()完成,只是一遍又一遍地循环“Hello”消息。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <ucontext.h>
static ucontext_t mainc, newthread;
void itake5seconds()
{
puts("Hello. I take 5 seconds to run.");
sleep(5);
puts("And I'm done! Wasn't that nice?");
}
void timer_handler(int signum)
{
puts("Doing some scheduler stuff.");
swapcontext(&mainc, &newthread);
}
int main(int argc, char* argv[])
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &timer_handler;
sigaction(SIGALRM, &sa, NULL);
getcontext(&newthread);
newthread.uc_stack.ss_sp = malloc(5000);
newthread.uc_stack.ss_size = 5000;
newthread.uc_link = &mainc;
makecontext(&newthread, &itake5seconds, 0);
struct itimerval timer;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 500000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 500000;
setitimer(ITIMER_REAL, &timer, NULL);
while(1);
return 0;
}
答案 0 :(得分:0)
您的代码在信号处理程序(swapcontext
)中调用“不安全”函数。因此,程序的行为是“未定义的”。
来自man 7 signal:
信号处理函数必须非常小心,因为其他地方的处理可能会在程序执行的某个任意点中断。 POSIX具有“安全功能”的概念。如果信号中断了不安全函数的执行,并且处理程序调用了不安全的函数,那么程序的行为是未定义的。
有关如何使用信号处理程序处理此问题的示例,请参阅Complete Context Control中的“SVID上下文处理示例”部分。但基本上你使用volatile int
全局变量来标记你的信号处理程序被调用,而是从正常代码执行swapcontext
调用(即不在信号处理的上下文中运行的代码)。
答案 1 :(得分:0)
问题是我没有保存swapcontext()返回其第一个参数的当前执行上下文。