0

setjmp()在 C 中可以使用和longjmp()在用户级别实现上下文切换来编码光纤。
evanjones.caPortable Multithreading(pdf)中所述,还要求每条光纤都有一个新分配的堆栈。
由于纤程存在于线程上下文中,当它被调用时,它会自动关联一个堆栈帧,那么为什么它需要这个新分配的堆栈呢?:当一根光纤想要切换到另一根时,可以使用以下方法:

 cpu_context[N] :global array where the i-th entry is the cpu context(jmp_buffer) of the i-th fiber 

fiber_ith :
   [...]
   if ( setjmp(cpu_context[i]) == 0 ){
        longjmp(cpu_context[j])
   }
   [...]

新堆栈的必要性是因为如此处所写 不可能使用 longjmp()返回到堆栈帧从光纤调用的那一刻起不再有效的光纤执行longjmp()

编辑:这些光纤必须是非抢占式的,并且可以自愿从一根光纤切换到另一根光纤

4

2 回答 2

3

假设光纤有一个函数调用另一个函数,该函数调用另一个函数,然后导致该光纤切换到另一根光纤。当我们恢复这个纤程时,我们需要确保所有局部变量都恢复到纤程切换时的状态,并且我们需要确保从这个函数返回到调用函数。因此出现以下规则:

  1. 在光纤运行时,它可以更改其堆栈。
  2. 当光纤恢复时,堆栈必须回到光纤切换时的位置。

从这两条规则可以立即得出,每根光纤都必须有自己的堆栈。

于 2018-07-26T21:19:10.880 回答
1

首先,线程并不打算手动控制它们自己的调度。也就是说,并不打算让一个线程决定结束或暂停其执行并启动另一个线程。相反,线程可以同时运行,并且系统可以同时在不同的物理或虚拟处理器上运行多个线程,或者可以启动和停止线程,以便它们共享处理器上的可用时间。

因为线程可能同时运行,所以它们必须有单独的堆栈。每个线程可能在更改和使用自己的堆栈的同时,其他线程正在更改和使用它们的堆栈。这些堆栈必须分开以避免冲突。

其次,setjmplongjmp用于跳转到线程状态的任意点。在同一个线程中,一个程序longjmp只能用于返回setjmp其当前调用堆栈中的前一个。例如,你不能做一些工作,用 记住状态Asetjmp做更多的工作,用 记住状态Bsetjmp然后longjmp到 state A,然后longjmp再到 state B。在longjmpto之后AB不再可用 - 为它保存的任何内容都setjmp不再有效。

于 2018-07-26T21:19:22.170 回答