【问题标题】:How to implement a practical fiber scheduler?如何实现一个实用的光纤调度器?
【发布时间】:2014-10-20 14:23:05
【问题描述】:

我了解使用协程作为基础和实现玩具调度程序的基本知识。但我认为这是对整个异步调度程序的过度简化的看法。我的想法中缺少一整套漏洞。

如何防止 CPU 运行空闲/等待的调度程序?一些纤程只是休眠,另一些则等待操作系统的输入。

【问题讨论】:

    标签: linux asynchronous scheduling language-implementation


    【解决方案1】:

    您需要将 io 操作多路复用到基于事件的接口(选择/轮询)中,因此您可以利用操作系统进行等待,同时仍然能够安排其他纤程。 select/poll 有一个超时参数 - 对于想要休眠的光纤,您可以创建一个优先级队列,使用该选项的 select/poll 来模拟休眠调用。

    尝试为执行阻塞操作(调用读/写/睡眠等)的纤程提供服务。除非您将每个光纤安排在本机线程中,否则直接无法正常工作 - 这会超出目的。

    请参阅http://swtch.com/libtask/ 以了解有效的实施。

    【讨论】:

    • libtask 看起来不错,但它似乎不允许明确的用户调度任务(我找不到将 CPU 分配给特定任务的 API)。我觉得 boost::context 看起来更通用,上面还有一层叫 boost::fiber 实现了不同任务之间的锁
    【解决方案2】:

    您可能应该看看 setcontext 系列函数 (http://en.wikipedia.org/wiki/Setcontext)。这意味着在您的应用程序中,您需要将所有可能阻塞(读取、写入、睡眠等)的函数重新实现为异步形式并返回到调度程序。

    只有“调度器纤程”才能使用 select()、poll() 或 epoll() 等待完成事件。这意味着当调度器空闲时,进程将在 select/poll/epoll 调用中休眠,不会占用 CPU。

    【讨论】:

    • setcontext 在完全不依赖机器堆栈的情况下如何实现它?我可以让协程等到另一个协程停止来模仿简单的调用。
    【解决方案3】:

    虽然回答有点晚了,但我想提一下,我有一个用 C 语言实现的 Fiber 库的实际实现,称为 libevfibers

    尽管是一个年轻的项目,但它已用于生产。它不仅为读/写套接字等经典异步操作提供了解决方案,而且还以非阻塞方式处理文件系统 IO。该项目利用了 3 个出色的库 --- libcoro、libev 和 libeio。

    【讨论】:

      【解决方案4】:

      您也可以通过使用协程来控制控制流。支持创建这些的库是 BOOST.ASIO。

      这里有一个很好的例子:Boost Stackful Coroutines

      【讨论】:

        【解决方案5】:

        从实现的角度来看,您可以从异步事件循环实现开始。然后,您可以通过使用异步事件处理程序切换到相应的纤程来实现纤程调度。

        睡眠/等待光纤只是意味着它目前没有被安排 - 它只是切换到事件循环。

        顺便说一句,如果您正在寻找一些实际代码,请查看http://svn.cmeerw.net/src/nginetd/trunk/,它仍在进行中,但尝试在多线程事件循环(使用 Win32 I/O 完成端口或 Linux 的边缘触发 epoll)。

        【讨论】:

          猜你喜欢
          • 2012-05-15
          • 2012-12-11
          • 2019-01-03
          • 1970-01-01
          • 1970-01-01
          • 2011-04-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多