select( )函数的作用
系统用select和poll两个系统调用来查询设备是否可读写,或者是否处于某种状态。
如果poll为空,则驱动设备会被认为即可读又可写,返回值为一个状态掩码。
select( )函数原型:
int select (int nfds, fd_set * readset, fd_set * writeset, fd_set * exceptset, struct timeval * timeout);
其中:
nfds: 需要检查的文件描述符的个数,数值应该比之后三组fd_set中最大数更大,而不是实际文件描述符的总数。
readset : 用来检查可读性的一组文件描述符。
writeset : 用来检查可写性的一组文件描述符。
exceptset: 用来检查意外状态的文件描述符。
timeout : NULL 指针代表无限等待,否则是指向timeval结构的指针,代表最长等待时间。
函数返回值: 响应操作的对应操作文件描述符的总数,且三组数据均在恰当位置被修改,只有响应操作的那些没有修改。
接着应该用FD_ISSET宏来查找返回的文件描述符组。
类型 fd_set
fd_set是一组文件描述符fd的集合。由于fd_set类型的长度在不同平台上不同,因此应该用一组标准的宏定义来处理此类变量:
- fd_set fd;
- FD_ZERO(&set); /*将set清零*/
- FD_SET (fd, &set); /*将fd加入set*/
- FD_CLR (fd, &set); /*将fd从set中清除*/
- FD_ISSET(fd, &set); /*如果fd在set中则真*/
一个例子:
- int isready ( int fd )
- {
- int rc;
- fd_set fds;
- struct timeval tv;
- FD_ZERO (&fds);
- FD_SET (fd, &fds);
- tv.tv_sec = tv.tv_usec =0;
- rc = select ( fd+1, &fds, NULL, NULL, &tv);
- // rc = select ( fd+1, &fds, NULL, NULL , NULL);
- if ( rc < 0 )
- {
- return -1;
- }
- return FD_ISSET (fd, &fds) ? 1 : 0;
- }
上面的例子是一个判断一个文件描述符可读性的例子。
如果我们把NULL指针作为fd_set传入的话,这就表示我们对这种操作的发生不感兴趣,但select() 还是会等待直到其发生或者超过等待时间。
[译 者注:在Linux中,timeout指的是程序在非sleep状态中度过的时间,而不是实际上过去的时间,这就会引起和非Linux平台移植上的时间不 等问题。移植问题还包括在System V风格中select()在函数退出前会把timeout设为未定义的 NULL状态,而在BSD中则不是这样, Linux在这点上遵从System V,因此在重复利用timeout指针问题上也应该注意。]
poll指向的函数返回 当前可否读写的信息。
1)如果当前可读写,返回读写信息。
2)如果当前不可读写,则阻塞进程,并等待驱动程序唤醒,重新调用poll函数,或超时返回。
3.驱动需要实现poll函数。
当驱动发现有数据可以读写时,通知核心层,核心层重新调用poll指向的函数查询信息。