API
select系统调用的用途是: 在一段指定时间内,监听用户感兴趣的文件描述符上的可读,可写和异常等事件。select原型如下:
#include <sys/select.h>
int select(int nfds, fd_set * rfd, fd_set * wfd, fd_set * excepfd, struct timeval * timeout);
nfds : 被监听的描述符个数。它通常被设置为select监听的所有文件描述符中的最大值加1,因为文件描述符从0开始计数。
rfd、wfd和excepfd*参数分别指向可读、可写和异常等事件的文件描述符集合。
fd_set * rset;
FD_ZERO(&rset);
FD_SET(int fd, &rset);
int FD_ISSET(fd, &rset);
FD_CRL(int fd, &rset);
select的特点:
- 可监控的事件: 可读,可写,异常
- 内核对fd_set集合在线修改,所以下次调用select前要重置这3个fd_set集合
- 支持的最大文件句柄个数是有限的
- 采用轮询来检查事件是否就绪,算法复杂度为O(n)
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
int main()
{
int fd, ret;
fd_set rset;
struct timeval timeout;
FD_ZERO(&rset);
while(1)
{
FD_SET(fd, &rset);//每次都要把fd从用户空间拷贝到内核空间
timeout.tv_sec = 5;//时间也需要重置
ret = select(fd+1, &rset, NULL, NULL, &timeout);
if ( -1 == ret)
{
printf("select error,errmsg = %s\n",strerror(errno));
return -1;
}
else if ( 0 == ret )
{
printf("select timeout\n");
continue;
}
else if ( ret > 0 )
{
if ( FD_ISSET(fd, &rset) )
{
dealwithEvent(fd);
}
}
}
}