编写linux应用程序时,经常会遇到需要检查好几个输入状态才能确定下一步行动的情况,这种情况可称之为忙等待。在单用户系统中运行一个忙等待是可以接受的,它不停地扫描
输入设备看是否有数据,如果有数据到达才读取它。这种做法很耗cpu时间。
select函数(这里函数又称调用、系统调用)检查一个由多个文件描述符组成的集合;如果集合中有描述符处于输入、输出、出错状态,select就返回处于这些状态的描述符个数。
描述符集合由数据结构fd_set实现,有一组定义好的宏可用来操作这些集合:
#inckude <sys/types.h>
#include <sys/time.h>
void FD_ZERO(fd_set *fdset); //将fdset所指的集合初始化为空集
void FD_CLR(int fd, fd_set *fdset); //将描述符fd从fdset所指的集合中移除
void FD_SET(int fd, fd_set *fdset); //将描述符fd添加到fdset所指的集合中
void FD_ISSET(int fd, fd_set *fdset); //判断fd是否在集合中
fd_set结构中所容纳的描述符数由FD_SETSIZE指定。
select函数还有一个超时值来防止它无限期地阻塞,这个超时值由结构体timeval结出:
#inckude <sys/types.h>
#include <sys/time.h>
struct timeval {
time_t tv_sec; //秒
long tv_usec; //微秒
};
timeout:有三种可能:1.timeout=NULL(阻塞:直到有一个fd位被置为1函数才返回)
2.timeout所指向的结构设为非零时间(等待固定时间:有一个fd位被置为1或者时间耗尽,函数均返回)
3.timeout所指向的结构,时间设为0(非阻塞:函数检查完每个fd后立即返回)
select函数的原型:
#inckude <sys/types.h>
#include <sys/time.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);select可同时判断集合中是否有描述符处于可读、可写、出错状态,它阻塞以等待某个描述符处于这些状态。参数nfds指定需要检查的描述符数目,范围是0-nfds-1。后面
的三个集合指针都可设为空,表示不进行这些状态的检查。如果没有描述的状态符合,select将在timeout指定的时间后返回0;如果timeout指针为空,函数将一直阻塞下去。
select返回时,描述符集合会被修改以指示哪些描述符正处于可读写或有错状态,用FD_ISSET找出需要注意的描述符。
select函数成功时返回状态发生变化的描述符数,失败返回-1并设置errno,可能的错误有:
EBADF 无效的描述符
EINTR 因中断产生的错误
EINVAL nfds或timeout取值错误