2010-05-06 82 views
5

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

我有表演的两个选项,IO操作:在EAGAIN

非阻塞模式,调查

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

轮询方式:轮询,然后执行

  1. 添加插座选择列表和轮询它。在正常模式下使用时
  2. 等待通知,这是可读可写的
  3. 读/写
  4. 后完成通知sucseeds的事件循环

对我来说,它看起来像第一次将需要更少的系统调用, 尤其适用于写入套接字(缓冲区相当大)。 此外,它看起来可以减少“select” 执行次数的开销,特别是当你没有可以很好地扩展为epoll/devpoll/kqueue的东西 时更是如此。

问题:

  • 有没有第二个方法的任何好处?
  • 在Linux,FreeBSD,Solaris,MacOSX,Windows等众多操作系统上,套接字/文件描述符上的非阻塞操作是否存在可移植性问题。

注:请不要建议使用现有的事件环/插座-API实现

回答

3

我不知道有任何跨平台的问题;最多只能使用Windows套接字API,但结果相同。

否则,你似乎在任何情况下轮询(避免阻塞等待),所以这两种方法都很好。只要你没有阻止自己的位置(例如,当没有数据时读取,当缓冲区已满时写入),它根本没有任何区别。

也许第一种方法更容易编码/理解;所以,去那。

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

2

第一个设计是Proactor Pattern,二是反应器模式的Reactor Pattern

一个好处是,你可以设计自己的API,这样你就不必分配读缓冲区,直到数据实际上是有被阅读。这可以减少您在等待I/O时的内存使用量。

+0

我看不出有什么理由不能等待分配内存直到需要使用第一种方法。我错过了什么吗? – Ioan 2010-05-10 18:47:59

+2

我想是这样,但实际上并没有这样实现。在第一种情况下,您需要步骤2-4中提供的缓冲区,在第二种情况下,您只需要在步骤3中使用缓冲区。 – karunski 2010-05-16 19:14:43

1

我与低延迟插座应用经验:

的写入 - 尝试直接从写线程写入插座(您需要获得该事件的循环互斥体),如果写不完整订阅写就绪带有事件循环(select/waitformultipleobjects),并在套接字可写时从事件循环线程写入

读取 - 总是“订阅”所有套接字的读取准备就绪,因此您总是在套接字获取时从事件循环线程中读取可读