asyncio底层:事件循环的实现原理
请解释Python asyncio事件循环(Event Loop)的底层实现原理。什么是事件循环?它是如何调度协程的?selectors模块在其中扮演什么角色?在Linux和Windows上分别使用什么I/O多路复用机制?
回答
我还是少年
事件循环(Event Loop)是什么?
事件循环是asyncio的核心,是一个无限循环,不断检查是否有待执行的回调、可读/可写的socket、已到期的定时器,并依次执行它们。
底层架构
Event Loop
├── _ready (队列) — 待执行的回调
├── _scheduled (堆) — 定时器回调(按到期时间排序)
└── _selector (Selectors) — I/O多路复用
主要流程(简化):
- 从
_scheduled堆中取出到期的定时器回调,移到_ready - 调用
selector.select(timeout)等待I/O事件 - 将就绪的I/O回调加入
_ready - 依次执行
_ready中的所有回调 - 回到步骤1
selectors模块
selectors模块封装了不同操作系统的I/O多路复用接口:
| 类 | 操作系统 | 底层调用 |
|------|---------|---------|
| SelectSelector | 通用 | select.select() |
| PollSelector | Linux | poll() |
| EpollSelector | Linux | epoll() |
| KqueueSelector | macOS/BSD | kqueue() |
| DevpollSelector | Solaris | /dev/poll |
| WindowsSelector | Windows | select() |
各平台具体实现
- Linux: 默认使用
epoll(事件驱动,大规模连接高效) - macOS/BSD: 使用
kqueue - Windows: 使用
IOCP(I/O Completion Ports,通过ProactorEventLoop)
自定义事件循环
import asyncio
import selectors
class CustomSelector(selectors.BaseSelector):
pass # 可实现自定义I/O复用逻辑
loop = asyncio.SelectorEventLoop(CustomSelector())
asyncio.set_event_loop(loop)