三个多路复用模型的概念
select
select 原理
select 是通过系统调用来监视着一个由多个文件描述符(file descriptor)组成的数组,当select()返回后,数组中就绪的文件描述符会被内核修改标记位(其实就是一个整数),使得进程可以获得这些文件描述符从而进行后续的读写操作。select饰通过遍历来监视整个数组的,而且每次遍历都是线性的。
select 优点
select目前几乎在所有的平台上支持,良好跨平台性。
select 缺点
- 每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多的时候会很大
- 单个进程能够监视的fd数量存在最大限制,在linux上默认为1024(可以通过修改宏定义或者重新编译内核的方式提升这个限制)
- 并且由于select的fd是放在数组中,并且每次都要线性遍历整个数组,当fd很多的时候,开销也很大
python select
调用select的函数为r, w, e = select.select(rlist, wlist, xlist[, timeout])
,前三个参数都分别是三个列表,数组中的对象均为waitable object
:均是整数的文件描述符(file descriptor)或者一个拥有返回文件描述符方法fileno()
的对象;
rlist
: 等待读就绪的listwlist
: 等待写就绪的listerrlist
: 等待“异常”的list
select方法用来监视文件描述符,如果文件描述符发生变化,则获取该描述符。
1、这三个list可以是一个空的list,但是接收3个空的list是依赖于系统的(在Linux上是可以接受的,但是在window上是不可以的)。
2、当 rlist
序列中的描述符发生可读时(accetp和read),则获取发生变化的描述符并添加到 r
序列中
3、当 wlist
序列中含有描述符时,则将该序列中所有的描述符添加到 w
序列中
4、当 errlist
序列中的句柄发生错误时,则将该发生错误的句柄添加到 e
序列中
5、当 超时时间 未设置,则select会一直阻塞,直到监听的描述符发生变化
当 超时时间 =
1
时,那么如果监听的句柄均无任何变化,则select会阻塞
1
秒,之后返回三个空列表,如果监听的描述符(fd)有变化,则直接执行。
6、在list中可以接受Ptython的的file
对象(比如sys.stdin
,或者会被open()
和os.open()
返回的object),socket object将会返回socket.socket()
。也可以自定义类,只要有一个合适的fileno()
的方法(需要真实返回一个文件描述符,而不是一个随机的整数)。