#inlcude <sys/select.h>
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
fd_set *restrict errorfds, struct timeval *restrict timeout);
参数:nfds给出了要监视的文件描述符的范围,其值至少比最大的文件描述符值大1.
readfds, writefds, errorfds分为为读操作,写操作和错误情况监视的文件描述符集,文件描述符集类型为fd_set。
timeout超时值,经过一段时间后, 即使没有准备就绪的描述符,他也会迫使select返回。timeout为NULL
时,select可能会无限期地阻塞。
返回: 成功时,返回已准备就绪的文件描述符的个数,并清空除已准备就绪的描述符之外
的,readfds,writefds,errorfds 中的所有描述符; 不成功,返回-1 并设errno。
必须设置的errno:
EBADF 一个或多个文件描述符集指定了无效的文件描述符
EINTR 在超时或被选中的时间发生之前被select信号中断
EINVAL 指定了一个无效的超时时间,或者nfds小于0或大于FD_SETSIZE
描述符集用比特掩码来实现。
相关函数:
void FD_CLR(int fd, fd_set *fdset);//清除fd对应的比特位
void FD_ISSET(int fd, fd_set *fdset);//测试fd对应的比特位是否被设置,被设置表示文件描述符存在
void FD_SET(int fd, fd_set *fdset);//设置fd对应的比特位
void FD_ZERO(fd_set *fdset);清楚fdset中所有的比特位
例子代码:
//用select进行两个并发文件拷贝的函数
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
int copy2files(int fromfd1, int tofd1, int fromfd2, int tofd2)
{
int bytesread, maxfd, num, totaltytes = 0;
fd_set readset;
if ((fromfd1 < 0) || (fromfd1 >= FD_SETSIZE) ||
(tofd1 <0) || (tofd1 >= FD_SETSIZE) ||
(fromfd2 < 0) || (fromfd2 >= FD_SETSIZE) ||
(tofd2 <0) || (tofd2 >= FD_SETSIZE) )
return 0;
maxfd = fromfd1; //找到最大的描述符
if (fromfd2 > maxfd)
maxfd = fromfd2;
for (; ; )
{
FD_ZERO(&readset);
FD_SET(fromfd1, &readset);
FD_SET(fromfd2, &readset);
if ((num = select(maxfd+1, &readset, NULL, NULL, NULL)) == -1) && (errno == EINTR))
continue;
if (num == -1)
return totalbytes;
if (FD_ISSET(fromfd1, &readset))
{
bytesread = readwrite(fromfd1, tofd1);
if (bytesread <= 0)
break;
totalbytes += bytesread;
}
if (FD_ISSET(fromfd2, &readset))
{
bytesread = readwrite(fromfd2, tofd2);
if (bytesread <= 0)
break;
totalbytes += bytesread;
}
}return totalbytes;
}