文件描述符
-
在Linux中,内核利用文件描述符即文件句柄,来访问文件。打开现存文件或新建文件时,内核会返回一个文件描述符,读写文件也需要使用文件描述符来指定待读写的文件。
-
文件描述符是非负整数。
fd_set结构体
fd_set可以理解为一个集合,这个集合中存放的是文件描述符即文件句柄。
fd_set集合可以通过下面的宏来进行人为来操作。
1、FD_ZERO
用法:FD_ZERO(fd_set*);
用来清空fd_set集合,即让fd_set集合不再包含任何文件句柄。
2、FD_SET
用法:FD_SET(int ,fd_set *);
用来将一个给定的文件描述符加入集合之中
3、FD_CLR
用法:FD_CLR(int ,fd_set*);
用来将一个给定的文件描述符从集合中删除
4、FD_ISSET
用法:FD_ISSET(int ,fd_set*);
检测fd在fdset集合中的状态是否变化,当检测到fd状态发生变化时返回真,否则,返回假(也可以认为集合中指定的文件描述符是否可以读写)。
select函数
用来监视需要监视的文件描述符(读或写的文件集中的文件描述符)的状态变化情况。并能通过返回的值告知我们。
int select(int maxfdp, fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout);
timeval的结构定义如下:
struct timeval{
long tv_sec; //秒
long tv_usec; //微秒
}
参数介绍
int maxfdp: 集合中所有文件描述符的范围,为所有文件描述符的最大值加1。
fd_set* readfds: 要进行监视的读文件集。
fd_set* writefds : 要进行监视的写文件集。
fd_set* errorfds: 用于监视异常数据。
struct timeval* timeout: 超时时间,它可以使select处于三种状态:
- NULL: 阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止
- 0: 纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值
- 大于0: 等待的超时时间,在timeout时间内阻塞,未超时如果有事件到来就返回,否则在超时后不管怎样一定返回
返回值
>0:被监视的文件描述符有变化; 返回就绪的文件描述符个数
-1:出错, 并设置errno
0 :超时;经过了timeout时长后仍无设备准备好,返回值为0
select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。
相关问题
如果select调用中设置了等待时间,那么每次调用时都需要重新对这个时间赋值么?
fd_set readfd;
struct timval tv;
while(1) {
FD_ZERO(&readfd);
FD_SET(fd, &readfd);
tv.tv_sec = 2;
tv.tv_usec = 0;
select(maxfd+1, &readfd, NULL, NULL, &tv);
......;
}
不可以, 因为tv在函数内部被改变了,时间会越来越来少,所以每次都要重新被赋值。
这个函数真是神通广大,用来定时也不错。