实现用户级线程包

时间:2012-02-04 22:48:26

标签: c multithreading

我已经在一个类中负责在C中创建一个用户级线程库。我想知道是否有人可以给我一个事项列表来阅读以实现这一目标。我对从哪里开始有一个好主意,但是用户级线程上的任何资源以及可能有用的C语言的一些适用方面都非常有价值。

我不清楚如何为此实现调度程序。假设我对C语言及其一些更有用的库函数有很好的理解。

3 个答案:

答案 0 :(得分:8)

我已完成家庭作业,而根本没有写任何汇编程序。线程切换机制是setjmp / longjmp。这涉及为每个线程的堆栈分配内存,然后非常仔细地按摩jmp_buff中的值,因此执行跳转到下一个线程的堆栈。

另见Russ Cox的可读性libtask

编辑以响应OP的评论:在决定何时切换线程时,有两个主要方向:抢先和&合作。在抢先模型中,你会有一些像定时器信号那样导致执行流程跳转到中央调度程序线程,该线程选择下一个运行的线程。在协作模型中,线程相互“明白”(例如,通过调用您将提供的yield()函数)或隐式地“产生”(例如 ,请求另一个线程持有的锁。)

查看libtask的API以获取合作模型的示例,尤其是函数taskyield()的描述。这是我提到的明确收益率。还有非阻塞I / O函数,其中包含隐式yield - 当前的“任务”被搁置,直到I / O完成,但其他任务有机会运行。

答案 1 :(得分:4)

可以使用swapcontext在C中完成一个简单的协作调度程序,查看swapcontext手册页here中的示例,这是它的输出:

$ ./a.out
main: swapcontext(&uctx_main, &uctx_func2)
func2: started
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: started
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: returning
func1: returning
main: exiting

所以你可以看到它是非常可行的。

注意:如果您在计时器信号处理程序中交换上下文,那么您自己就是一个先发制人的调度程序,但我不确定这样做是否安全或可行。

编辑:我在sigaction的手册页中发现了这一点,这表明可以在信号处理程序中切换上下文:

  

如果在sa_flags中指定了SA_SIGINFO,那么sa_sigaction(而不是   sa_handler)指定signum的信号处理函数。   该函数接收信号编号作为其第一个参数a   指向siginfo_t的指针作为其第二个参数和指向a的指针   ucontext_t (强制转换为void *)作为其第三个参数。

答案 2 :(得分:1)

您可以查看Apple的开源实现。请注意,代码的最大部分实际上是汇编代码,因为它需要一些您无法在C中执行的特殊操作,例如检索堆栈帧的返回地址或跳转到任意地址。

Userland线程(通常也称为“光纤”)通常采用合作模型;也就是说,线程执行直到他们确定他们有足够的时间,然后屈服于另一个线程。使用优先级队列,您可以实现一个调度程序,该调度程序执行已运行最短时间的任务。 (调度程序会跟踪正在运行的任务,并且当运行任务确定已经足够时,运行任务会返回。调度程序会更新任务运行的时间,然后生成执行时间最短的任务。)