我正在使用<ucontext.h>
在我的“任务管理器”程序中的不同任务之间进行交换。任务(功能)在一个链表中,定时器定期向信号处理程序发送信号,信号处理程序将当前上下文交换到列表中的下一个任务。
问题是我需要一个无限循环来保持程序运行,因为否则它会在计时器有机会发送下一个信号之前终止。我处理这个问题的方法是在每个任务(函数)结束时打一个无限循环,这样计时器就有时间发送信号。我不认为这是保持程序运行的好方法,所以我想知道是否有一种方法可以创建某种“全局”循环,无论我当前所处的上下文如何,它都可以继续运行。把它放在“main”函数中并不起作用,因为我离开主上下文是为了进入其他上下文。
#include <malloc.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <ucontext.h>
#include <unistd.h>
#define FIBER_STACK 1024 * 64
ucontext_t uctx_func1, uctx_func2, uctx_func3, uctx_main;
struct elem {
ucontext_t context;
struct elem *prev;
struct elem *next;
};
struct elem *start = NULL;
struct elem *current = NULL;
void signal_handler();
void push(ucontext_t context); // end
void pop(); // start
void fiber1(); // these are my tasks
void fiber2(); // these are my tasks
void fiber3(); // these are my tasks
void create_task(void (*start_routine)(), ucontext_t context);
void setHandler(struct sigaction sa);
void setTimer(struct itimerval timer);
void main() {
struct sigaction sa;
struct itimerval timer;
create_task(fiber1, uctx_func1);
create_task(fiber2, uctx_func2);
create_task(fiber3, uctx_func3);
setHandler(sa);
setTimer(timer);
current = start;
swapcontext(&uctx_main, ¤t->context);
}
void signal_handler() {
struct elem *temp = current;
current = current->next;
pop();
push(temp->context);
swapcontext(&temp->context, ¤t->context);
}
void create_task(void (*start_routine)(), ucontext_t context) {
getcontext(&context);
context.uc_link = NULL;
context.uc_stack.ss_sp = malloc(FIBER_STACK);
context.uc_stack.ss_size = FIBER_STACK;
context.uc_stack.ss_flags = 0;
makecontext(&context, start_routine, 0);
push(context);
}
void fiber1() {
printf("++++++++++\n");
while (true) {
} // these are the infinite loops I want to get rid of
}
void fiber2() {
printf("----------\n");
while (true) {
} // these are the infinite loops I want to get rid of
}
void fiber3() {
printf("**********\n");
while (true) {
} // these are the infinite loops I want to get rid of
}
void push(ucontext_t context) {
struct elem *p = start, *q;
if (start) {
q = (struct elem *)malloc(sizeof(struct elem));
q->context = context;
q->next = NULL;
while (p->next)
p = p->next;
p->next = q;
q->prev = p;
}
else {
start = (struct elem *)malloc(sizeof(struct elem));
start->context = context;
start->prev = NULL;
start->next = p;
}
// printf ("Element Added.\n");
}
void pop() {
if (start) {
start = start->next;
// printf ("Element Deleted.\n");
}
else
printf("Queue is empty.\n");
}
void setHandler(struct sigaction sa) {
sa.sa_handler = signal_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGALRM, &sa, NULL) == -1)
perror("sigaction");
}
void setTimer(struct itimerval timer) {
timer.it_interval.tv_sec = 0;
timer.it_value.tv_sec = 0;
timer.it_interval.tv_usec = 10000;
timer.it_value.tv_usec = 10000;
if (setitimer(ITIMER_REAL, &timer, NULL) == -1)
perror("setitimer");
}
1条答案
按热度按时间icnyk63a1#
创建一个wrapper函数:
然后按如下方式更改
create_task
:**编辑:**正如注解中所指出的,
makecontext
的可变参数不能是函数指针,必须是int
。为了解决这个问题,可以创建一个“任务”的全局数组-即函数指针,并将数组索引作为参数传递。因此,修改答案,它看起来像: