select poll epoll详解(深入理解select、poll、epoll)
深入理解select、poll、epoll
介绍
在网络编程中,常常需要同时处理多个socket的I/O事件。为了实现高效的事件处理,Linux提供了select、poll、epoll三种机制。它们均可以用于等待一个或多个socket的读写事件,是事件驱动编程中不可缺少的一部分。但它们各自的实现以及优劣性还是有所不同的。
select机制
select机制是最古老的事件通知机制之一,其实现方式是将需要监控的文件描述符(fd)全部存放到一个fd_set结构体中,并传入select系统调用中,select会阻塞进程直到有一个或多个fd就绪。fd_set是一个位数组,可以通过FD_SET、FD_CLR等宏来设置fd。但一个进程能够监控的fd是有限制的,一般是1024个。并且每次调用select时,都需要将所有需要监控的fd从用户空间拷贝到内核空间,造成一定的性能损失。在这种情况下,多个进程调用select容易导致效率下降。
poll机制
poll机制使用的数据结构与select有所不同,它使用了一个pollfd结构体数组,用户可以将需要监控的fd存放到其中,然后将整个数组传递给poll系统调用。与select相比,poll没有fd数量限制。但每次poll调用时,都需要将整个pollfd数组从用户空间拷贝到内核空间,性能表现并不理想。在fork后的子进程中也需要重新设置pollfd数组,这不容易实现代码的复用。
epoll机制
epoll是Linux内核2.6版本中引入的一种高效的事件通知机制。在epoll中,通过epoll_create创建epoll实例,将需要监控的fd存放到其中,然后通过epoll_wait等待事件触发。与select、poll相比,epoll具有以下优点:(1)没有文件描述符数量限制;(2)触发事件时,只返回就绪的fd,避免了每次遍历整个fd集合;(3)可以较好地支持异步I/O;(4)通过mmap提高了性能表现。
总结
三种机制都提供了方便的I/O多路复用,但效率和灵活性却有所不同。select机制已经落后于时代,poll机制成为了替代select的一种选择。而epoll机制则可以说是目前I/O多路复用中的首选。当然,选择何种机制也需要根据实际情况。在大多数情况下,使用epoll会比使用select或poll更加高效。