Continuation Systems
本文的语气或风格 可能无法反映整个wiki使用的百科全书式语气。 有关建议,请参阅 Wikipedia's article on tone |
分时工作原理是中断正在运行的程序,并将其运行时状态(如程序计数器和寄存器)保存到数据结构(通常是内核级堆栈)中。 从理论上讲,保存的状态构成了中断程序的one-shot continuation。 (译者注:这里continuation可以翻译为名词-延续,但是中文延续有动词的意像,容易产生误解,所以以下不翻译了。这里的意思有点类似传承的“香火”,指对于要被移出运行空间的线程的信息保持,用以将来再次唤醒线程。) 实际上关于continuation还有其它操作,在基于线程的系统中切换线程涉及将旧线程的continuation保存到该线程的数据结构中,然后从新线程加载并抛出新的continuation。 为continuations添加复制操作允许用户程序决定何时使用昂贵的multi-shot continuations。 最后,添加一个操作来挂起当前continuation,并将其作为值传递给指定的新continuation,从而使continuation能够完成通信 -- 向continuation发送一个可能包含其调用程序的值。
因为保存的continuation不能代表当前运行的程序,所以需要虚拟处理器(virtual processors)的概念。 它们通过存储内核的状态信息来表示当前的continuation,用于当前的计算,并通过机器处理器进行抽象。 通过为每个逻辑处理器创建虚拟处理器抽象,内核可以使用虚拟处理器来支持多处理器或多核机器。
我们可以很容易地看到一个类比:虚拟处理器的外观和行为类似于正在运行的线程,而保存的continuations的外观和行为类似于挂起的线程。
Scheme和ML程序员多年来一直知道如何使用协同程序的continuations来创建协作线程系统,但抢占式系统(就像大多数操作系统创建者所希望的那样)需要某种机制来抢占正在运行的程序。 添加一个事件(event)抽象可以实现这一点。 这些事件可以包含为“处理程序”保存的任意数量的延续,并支持“fire”或“trigger”触发事件的操作。 当某个事件触发时,它会将其所有处理程序出列,并将它们交给调度器,该调度器只需要决定哪种event-handler continuations可以抢占哪种正在运行的虚拟处理器。 当调度程序决定抢占时,它只是将抢占的continuation作为一个值传递给抢占的continuation,可能会检查抢占的continuation完成时收到的返回值,以查找错误代码。 为处理程序提供抢占continuation,使其能够执行更高级别的调度操作,可能会将内核中甚至L4保留的函数移出处理程序。
注意,事件可以作为对机器中断的方便抽象。 这样使用它们可以方便地将硬件对抢占的支持转换为操作系统对抢占的支持。
然而,在当前操作集中添加一个continuation作为事件处理程序将运行得太慢,无法真正使用。 相反,事件获得一个新操作,该操作将current continuation添加到给定事件的处理程序集,然后使用“给定值”调用“given continuation”。 这样设计的原语才可以更高效地运行。
最后,添加一个额外的基本操作将有助于将这个并发系统带入多核和多处理器机器的真正并行世界。 由于一个continuation不能在不切换到另一个continuation的情况下自行终止,虚拟处理器甚至可以在启动后永远运行。 只需要一个原语就可以用给定的continuation和值启动非活动的虚拟处理器。
总之,continuation;虚拟处理器;通过给用户空间或更高级别的内核对处理器复用的控制,事件可以用来在正常进程之上构建复杂的并发和并行模型。
一个有趣的附带问题:假设内核使事件以并行安全的方式工作,那么事件可以用来实现标准的同步对象吗? 可以很容易地证明,事件将足以实现同步阻塞变量,但信号量呢?