IO 多路复用

IO 多路复用是通过一种机制,同时监视多个文件描述符,一旦某个文件描述符就绪(比如读就绪或写就绪),会通知应用程序进行相应的处理 select、poll、epoll 本质上都是同步 IO,它们都需要在事件就绪后,由应用程序自己进行读写。而异步 IO 不需要应用程序自己进行读写,异步 IO 实现负责把数据从内核拷贝到用户空间。

Linux 提供 select、poll、epoll,来实现 IO 多路复用机制,下面将对它们进行简要的介绍。


select、poll

如果想了解 select、poll 的原型和详细说明,请点击该链接。这里只对 select 和 poll 的执行过程,进行简要的说明:


epoll

如果想了解 epoll,请点击该链接

epoll 的使用过程如下:

与 select、poll 相比,epoll 有如下特点:


水平触发和边缘触发

epoll 有水平触发边缘触发两种模式。水平触发是默认模式,边缘触发是高速模式。在水平触发模式下,如果一个描述符有数据可读,那么每次调用 epoll_wait 都会返回该描述符上发生的事件。而在边缘触发模式下,只会提醒一次,直到有新数据流入。因此在边缘触发模式下,读描述符一定要读空它的 buffer,即一直读到 read 的返回值小于它的请求值,或遇到 EAGAIN 错误(读非阻塞 socket 时,如果输入缓冲区中没有数据,那么会出现 EAGAIN 错误,意思是告诉应用程序再读一次或许就有数据了)。


文件描述符

当进程打开或新建文件时,内核会返回一个文件描述符,文件描述符是一个非负整数,取值范围是 0 到 max open files。

内核会为每个进程维护一个保存该进程打开的文件的记录表,文件描述符是这个记录表中的索引值,内核利用文件描述符来访问文件。

通常标准输入的文件描述符是 0,标准输出的文件描述符是 1,标准错误输出的文件描述符是 2。


epoll in Python

Python 标准库的 select 模块,提供访问操作系统的 IO 多路复用接口的功能。select 的文档在:https://docs.python.org/3/library/select.html

下面主要介绍其中关于 epoll 的部分:


参考文档