select:在一段时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。
poll:和select类似,也是在一段时间内轮询一定数量的文件描述符,监听是否有就绪的文件描述符。
epoll:使用一组函数来完成任务,epoll把关心的文件描述符的事件放入内核事件表中,每次只用监听内核事件表中的就绪事件即可。
1、三者函数原型不同
int select( int nfds ,struct fd_set* readfds ,fd_set* writefds ,fd_set* exceptfds, struct timeval* timeout)
参数:
nfds:被监听的文件描述符的总数。
readfds /writefds / exceptfds:分别指向可读、可写和异常事件对应的文件描述符集合。应用程序调用select函数时,通过这三个参数传入自习感兴趣的文件描述符,select调用返回时,内核修改它们来通知应用程序哪些文件描述符已经就绪。
timeout:设置超时时间
int poll(struct pollfd* fds ,nfds_t nfds,int timeout)
fds:是pollfd类型的数组,它指定文件描述符上发生的事件。Pollfd结构体定义如下:
struct pollfd{
int fd;文件描述符
short events;注册事件
short revents;实际发生的事件,由内核填写
}
nfds:指定监听事件集合fds的大小
timeout:指定超时时间
epoll的三个函数
int epoll_create(int size),创建一个额外的内核事件表,size是事件表的大小。
int epoll_ctl(int epfd ,int op, int fd,epoll_event* event),根据op参数的操作类型,对事件表进行操作。
int epoll_wait(int epfd,epoll_event *events ,int maxevents ,int timeout),从就绪链表中取就绪事件的描述符和事件
2、使用方面的区别
select函数通过3个fd_set结构体变量分别为内核传递用户关注的可读、可写和异常事件。故select不能处理更多的事件类型,并且内核也通过这三个结构体变量返回就绪的文件描述符,所以每次使用之前,都要重新设置这3个结构体变量。
poll函数将用户关注的文件描述符以及其关注的事件、内核返回的文件描述符发生的事件分离表示,并且通过一个用户数组将所有的文件描述符传递给内核,因此,poll能关注的事件类型更多,每次调用不需要重新设置。
epoll是通过一组函数来完成,通过epoll_create创建一个内核事件表,通过epoll——ctl函数添加、删除和修改事件。Epoll_wait只需要从内核事件表中读取用户的注册事件即可。
3、使用限制
select关注的文件描述符最多1024个,poll和epoll都能达到65535个
4、使用效率
select、poll每次调用都需要将用户空间的文件描述符拷贝到内核空间,epoll则只需要拷贝一次,效率更高。
select、poll每次都要将所有的文件描述符返回,所以应用程序检索就绪文件描述符为O(n)。Epoll通过通过events参数返回所有就绪的文件描述符,应用程序检索就绪的文件描述符的时间复杂度是O(1)。
select、poll只能工作在LT模式下,而epoll可以在ET模式下工作,更高效。