ioloop 即io事件处理轮询
本文就从下面这个 Tornado 官方的例子程序开始:
| 
 | 
 | 
以 tornado.ioloop.IOLoop().current().start() 为起点,切入 ioloop 的处理过程。首先程序来到类 IOLoop 的 current 方法:
| 
 | 
 | 
IOLoop 的父类为 Configurable,其使用 new() 方法进行初始化(new()方法在init()方法之前被调用,它可以决定一个类是否使用init()方法进行初始化)。
| 
 | 
 | 
Configurable 类中的 new() 方法中,根据具体实现类(子类)继承实现的几个重要方法来完成本身的初始化,new() 方法其实是一个工厂方法。其中,cls.configured_class() 方法获取本次运行环境下的使用的轮询方式(比如epoll/kqueue/select):
| 
 | 
 | 
测试环境为centos,返回值为 EPollIOLoop 。我们来看下其实现:
| 
 | 
 | 
EPollIOLoop 从 PollIOLoop 继承而来,而且impl默认值为 select.epoll()。文章最开始的例子中的 tornado.ioloop.IOLoop().current().start() 其实就是类 PollIOLoop 的 start() 方法,我们看下该类的 initialize() 和 start() 方法:
| 
 | 
 | 
initialize() 方法中做了实际的初始化工作,后续再详细展开细节的研究,暂时略过。
start() 方法中重点看下 event_pairs = self._impl.poll(poll_timeout) ,其作用就是使 epoll 进入等待状态。当有IO任务处于就绪状态时,该方法返回 event_pairs。self._events.update(event_pairs) 将就绪任务记录到 self._events ,根据fd从 self._handlers 中对应取出 handler_func 处理函数,并且将该函数作为就绪事件的回调函数,执行真正的IO处理工作。