我正在做一个家庭作业,下学期就要交了。它要求我们使用 ucontext API来实现我们自己的上下文切换/线程库。教授提供了实现这一点的代码,但在线程返回之前,他手动做了一些工作,并调用一个ISR,该ISR找到另一个要使用的线程,并将上下文切换到该线程,如果没有剩余的线程,则退出。
赋值的重点是使用上下文的 uc_link 字段,这样当它遇到return时,它就可以处理这项工作。我创建了一个函数(类型为void/void args),它只做以前函数所做的工作(清理,然后调用ISR)。教授说他想要这样做。
因此,剩下的工作就是在 uc_link 字段中的上下文上执行 makecontext,以便它运行我的线程,对吗?当我在 ucontext_t 和函数的任意组合上执行 makecontext 时,我得到了一个segfault,gdb没有提供任何帮助。我可以跳过 makecontext,当我的程序在我创建的线程中遇到一个return时,它会“正常”退出,因为(大概)uc_link 字段没有正确设置(这正是我要做的)。
我也找不到任何关于为什么 makecontext 会出现segfault的信息。有人能帮忙吗?
stack2.ss_sp = (void *)(malloc(STACKSIZE));
if(stack2.ss_sp == NULL){
printf("thread failed to get stack space\n");
exit(8);
}
stack2.ss_size = STACKSIZE;
stack2.ss_flags = 0;
if(getcontext(&main_context) == -1){
perror("getcontext in t_init, rtn_env");
exit(5);
}
//main_context.uc_stack = t_state[i].mystk;
main_context.uc_stack = stack2;
main_context.uc_link = 0;
makecontext(&main_context, (void (*)(void))thread_rtn, 0);
我还尝试了 thread_rtn、&thread_rtn 和其他方法。thread_rtn 被声明为 void thread_rtn(void)。
稍后,在每个线程中(run_env 的类型为 ucontext_t):...
t_state[i].run_env.uc_link = &main_context;
3条答案
按热度按时间c3frrgcw1#
这里有很多事情要做,但我会给予我最好的想法。我也试图在不解决家庭作业的情况下回答问题。
thread_rtn
是在什么上下文中声明的?它是否使用了任何非静态变量?segfault可能是由已分配但不再可用(超出上下文或已释放)的内存引起的。
我无法判断
main_context
是否与线程上下文相同,两者应该不同。看起来每个线程都需要自己的堆栈,它不应该和主上下文的堆栈相同(或者和其他线程的堆栈相同)。想一想每个线程可以从哪里获得内存作为堆栈使用。在什么情况下
malloc(STACKSIZE)
会返回NULL
?当线程上下文被添加到主上下文时,
main_context.uc_link
应该递增。看起来main_context.uc_link
正在跟踪有多少线程链接到主上下文。(我试图留下一些与课程相关的思考工作,而不是说明如何处理递减的计数)。注意特殊值0,表示不再有任何线程与此主上下文关联。main_context.uc_link
是否有最大值?希望这对你有帮助。
a11xaf1n2#
我有完全相同的问题,经过相当多的调试,我找到了解决方案。
makecontext()要求你传递栈底,它会根据传递给它的大小自动计算栈顶。
就我而言,
因为在linux中,堆栈是从上到下增长的,我传递的是clone系统调用所要求的栈顶,所以,它会产生分段错误。
试试看,也许有用。
h4cxqtbf3#
我遇到了同样的错误,我弄清楚了,错误的原因是堆栈的大小太小,增加它,错误就消失了。