内核提供的多路分离函数select()
是建立IO多路复用模型
的基础
select()可以避免同步非阻塞模型中的轮询等待
的问题。在这种模式下,我们先将需要进行IO操作的socket加入到select中
,然后便阻塞等待select()系统调用返回。有数据到达时,socket便被激活,select函数返回
,此时用户线程发起read请求,读取数据便继续执行。
select虽然在流程上与同步阻塞IO相同,并且还要监视socket。但select最大的优势在于用户可以在一个线程内处理多个socket的IO请求
。可以注册多个socket,并不断调用select读取被激活的socket
。
select优点
select()的可移植性更好,在某些Unix系统上不支持poll()
select()对于超时值提供了更好的精度:微秒,而poll是毫秒。
select缺点
- 调用select,会把
文件描述符从用户态拷贝到内核态
,并且内核需要遍历所有的文件描述符,文件描述符越多,系统开销越大
。 - 对
fd进行扫描时是线性扫描
。fd剧增后,IO效率较低,
因为每次调用都对fd进行线性扫描遍历,所以随着fd的增加会造成遍历速度慢的性能问题 - 一个进程
能够监视的文件描述符的数量存在限制
,Linux上通常为1024
。 - select() 函数的
超时参数在返回时也是未定义的
,考虑到可移植性,每次在超时之后在下一次进入到select之前都需要重新设置超时参数。