1、函数原型:
int select(int nfds, struct fd_set *readfds, struct fd_set *writefds,
struct fd_set *execptfds, struct timeval * timeout);
int poll(struct pollfd * fds, nfds_t fds, int timeout);
epoll:
int epoll_create(int size);
int epoll_ctl(int epollfd,int op,int fd,struct epoll_event* event);
int epoll_wait(int epollfd, struct epoll_event *events,
int maxevents, int timeout);
2、使用方面:
select函数通过三个fd_set结构体变量分别给内核传递用户关注的所有可读、可写、异常事件,这使得select不能处理更多的事件类型,并且内核也通过这三个结构体变量返回就绪的文件描述符,所以每次使用之前,都必须重新设置这三个结构体变量。
poll函数将用户关注的文件描述符以及其关注的事件、内核返回的文件描述符上发生的事件分离开表示,并且通过 一个用户数组将所有的文件描述符传递给内核。因此,poll函数能关注的事件类型更多,每次调用也不需要重新设置。
epoll是通过一组函数来完成的,epoll通过epoll_create创建一个内核事件表,通过epoll_ctl函数添加、删除、修改事件。epoll_wait只需要从内核事件表中读取用户的注册的事件。
3、使用限制:
select所使用的fd_set结构实际上是一个整形数组,32bit系统上关注的文件描述符最多1024个,最大文件描述符数1023.
poll和epoll分别用nfds和maxevents参数指定最多监听多少个文件描述符,这两个数值都能达到系统允许打开的最大文件描述符数。(65535)ua
4、使用效率:
1、select、poll每次调用都需要将用户空间的文件描述符拷贝到内核空间,epoll则只需要拷贝一次。效率更高。
2、select、poll每次都将所有的文件描述符(就绪的和未就绪的)返回,所以应用程序检索就绪文件描述符的时间复杂度为O(n),epoll通过events参数返回所有就绪的文件描述符,应用程序检索就绪文件描述符的时间复杂度为O(1)。
3、 select、poll只能工作在效率较低的LT模式,而epoll则能工作在ET高效模式,并且epoll还支持EPOLLONESHOT事件,从而进一步减少事件被触发的次数。
5、内核效率:
select和poll采用轮询的方式:即每次都需要扫描整个注册的文件描述符集合,并将其中就绪的文件描述符返回给用户程序,因此,内核中检测就绪文件描述符的算法时间复杂度为O(n), epoll则采取回调的方式,内核检测到就绪文件描述符,就触发回调函数,将文件描述符及发生的事件插入内核就绪事件队列,因此,epoll在内核中检测就绪文件描述符的算法时间复杂度为O(1)。但是,当链接的活动比较频繁是,select和poll的效率比epoll要高,因为epoll的回调函数调用过去频繁,所以,epoll适用于链接较多,但是活动不频繁的情况。