select
int select (int maxfds,fd_set * readfds,fd_set * writefds,fd_set * errorfds,struct timeval* timeout)
返回值:有变化的描述符,返回值大于零,且为描述符个数;等于零,超时或者没有变化的描述符;-1出错。
timeout参数
1)null时,select将会一直阻塞,直到有监听的描述符集合里面描述符发生了变化;
2)0时,select 会立即返回,有无描述符发生变化都会立即返回;
3)大于零的值,指定超时时间,超出时间就返回;
Poll
int poll (struct pollfd* fds , unsigned int nfds , int timeout)
struct pollfd{
int fd;
short events;
short revents;
}
返回值:大于零,返回revents中不为0的文件描述符个数;等于零,超时或者没有描述符就绪;-1,调用出错。
timeout参数:
1)负数,无限超时;一直等待,直到一个指定的事件发生; 相当于selsect中的NULL;
2)0;表示立即返回;无论是否有已经准备好的描述符;
3)大于零,指定等待的超时时间;超时后返回
epoll
创建epoll句柄
int epoll_create (int size);
向内核注册,修改或者删除 一个描述符
int epoll_ctl (int epfd, int operator , int fd , struct epoll_events * event );
等待事件的产生
int epoll_wait (int epfd, struct epoll_events*events , int maxevents , int timeout);
timeout参数:0立即返回,-1将永久阻塞直到有一个描述符有事件产生;大于零,指定超时时间
select、poll、epoll的区别
1)select : 描述符集合有上限,一般是1024/2048;每次需要线性遍历描述符集合获得描述符的事件状态,对于分布的比较稀疏的比较少的描述符,效率会很低;每次fd_set在select返回之后都会发生变化;需要重新初始化;但移植性比较好,在某些unix系统上不支持poll,超时时间精度比较高!
2)poll相对于select而言,描述符数量远远大于select,是哟个特定大小的数组来保存监控的描述符,从而不受描述符值大小的影响;poll将监控的输入事件和输出事件分开,允许在每次返回后,被监控的文件数组可以被复用而不需要重新初始化;
3)epoll 使用一个文件描述符管理多个描述符。支持一个进程打开大数目的描述符,也即是描述符数量不受限制,对于支持上万连接的IM服务器而言,较为实用!上限是最大可以打开的文件数目;IO效率不随描述符的数量的增加而减少。在每个注册到内核的fd上实现了回调函数,只有当当前socket活跃的时候才会去调用回调函数,所以epoll只会对活跃的socket进行操作(即事件驱动)。而select/poll要线性扫描所有的集合,导致效率下降。epoll将用户关系的文件描述符的事件存放到内核的事件表中,避免了用户空间和内核空间数据的多次拷贝