【问题标题】:Asynchronous event loop design and issues异步事件循环设计和问题
【发布时间】:2011-02-16 07:38:23
【问题描述】:

我正在使用 epoll/devpoll/kqueue/poll/select(包括 windows-select)为异步套接字 IO 设计事件循环。

我有两种执行方式,IO操作:

非阻塞模式,在 EAGAIN 上轮询

  1. 将套接字设置为非阻塞模式。
  2. 读/写到套接字。
  3. 如果操作成功,将完成通知发布到事件循环。
  4. 如果我得到 EAGAIN,请将套接字添加到“选择列表”并轮询套接字。

轮询方式:轮询后执行

  1. 将套接字添加到选择列表并轮询它。
  2. 等待通知它可读可写
  3. 读/写
  4. 将完成通知发布到成功的事件循环

在我看来,在正常模式下使用时首先需要更少的系统调用, 特别是对于写入套接字(缓冲区非常大)。 此外,看起来有可能减少“选择”数量的开销 处决,特别是当你没有可以很好地扩展的东西时 作为 epoll/devpoll/kqueue。

问题:

  • 第二种方法有什么优势吗?
  • 在多种操作系统上对套接字/文件描述符进行非阻塞操作是否存在可移植性问题:Linux、FreeBSD、Solaris、MacOSX、Windows。

注意事项:请不要建议使用现有的 event-loop/socket-api 实现

【问题讨论】:

    标签: c++ c asynchronous nonblocking event-loop


    【解决方案1】:

    我不确定是否存在跨平台问题;最多只能使用 Windows Sockets API,但结果相同。

    否则,无论哪种情况,您似乎都在进行轮询(避免阻塞等待),因此两种方法都可以。只要你不让自己处于阻塞的位置(例如,在没有数据时读取,在缓冲区满时写入),完全没有区别。

    也许第一种方法更容易编码/理解;所以,就这样吧。

    您可能有兴趣查看libevc10k problem 的文档,了解有关此主题的有趣想法/方法。

    【讨论】:

      【解决方案2】:

      第一个设计是Proactor Pattern,第二个是Reactor Pattern

      反应器模式的一个优点是,您可以设计您的 API,这样您就不必分配读取缓冲区,直到数据实际可供读取。这可以减少等待 I/O 时的内存使用量。

      【讨论】:

      • 我看不出有什么理由让您迫不及待地使用第一种方法分配内存。我错过了什么吗?
      • 我想是这样,但实际上并没有以这种方式实现。在第一种情况下,您需要步骤 2-4 中可用的缓冲区,在第二种情况下,您只需要在步骤 3 中使用它。
      【解决方案3】:

      根据我使用低延迟套接字应用程序的经验:

      for writes - 尝试从写入线程直接写入套接字(您需要为此获取事件循环互斥锁),如果写入不完整,请订阅事件循环(select/waitformultipleobjects)的写入准备并从事件循环线程写入当套接字可写时

      用于读取 - 始终“订阅”所有套接字的读取就绪状态,因此当套接字变得可读时,您始终从事件循环线程中读取

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-07
        • 1970-01-01
        • 2019-01-12
        • 2021-07-17
        • 2019-05-16
        相关资源
        最近更新 更多