搞Linux 服务器开发的人肯定了解 select、poll、epoll,他们都是基于事件驱动的IO多路复用技术,而他们之间的区别网上已经有很多的文章了,大家可以去详细的阅读,我在这里主要想写写我对epoll的底层实现的理解。
首先还是先说说 select、poll相比与epoll来说他们效率低下的原因吧:
select、poll、epoll是Linux平台下的IO多路复用技术,适合用来管理大量的文件描述符,但是这些系统调用本身是阻塞的,而他们管理的socket描述符其实是可以阻塞,也可以非阻塞的,但是大部分情况下设置为非阻塞的要更好一些,效率会更高一些。因此,他们并不是真正的异步IO。是伪异步的。
1、select
首先,select的缺点1:是select管理的描述符的数量在不重新编译内核的情况下是一个固定的值:1024,当然,重新编译了Linux内核之后,这个数值可以继续增大到用户的需求,但是这是相对来说比较麻烦的一件事。
其次。select的缺点2:是select对于socket描述符的管理方式,因为Linux内核对select的实现方式为每次返回前都要对所有的描述符进行一遍遍历,然后将有事件发生的socket描述符放到描述符集合里,然后将这个描述符集合返回。这种情况对于描述符的数量不是很大的时候还是可以的,但是当描述符达到数十万,甚至上百万的时候,select的效率就会急剧的降低,因为这样的轮询机制会造成大量的浪费和资源开销。因为每一次的轮询都要将这些所有的socket描述符从用户态拷贝到内核态,在内核态,进行轮询,查看是否有事件发生,这是select的底层需要做的。而这些拷贝完全是可以避免的。
2、poll
poll的实现机制和select是一样的,也是采用轮询机制来查看有事件发生的socket描述符,所以效率也是很低,但是poll对select有一项改进就是能够监视的描述符是任意大小的而不是局限在一个较小的数值上(当然这个描述符的大小也是需要操作系统来支持的)。
综上:在总结一下,select与poll