select函数用来查询设备是否可读写,或是否处于某种状态。 select()函数说明:
select()函数的接口主要是建立在结构'fd_set'的基础上。'fd_set' 是一组文件描述符(fd)的集合。由于fd_set类型的长度在不同平台上不同,所以linux用一组标准的宏定义来处理此类变量:
fd_set set;
FD_ZERO(&set); /* 将set清零 */
FD_SET(fd, &set); /* 将新的文件描述符fd加入set */
FD_CLR(fd, &set); /* 将fd从set中清除 */
FD_ISSET(fd, &set); /* 如果fd在set集中,则返回真 */
不同系统平台,一个fd_set集的最大描述符不同,不过你可以通过sizeof(fd_set) 的返回来判断你的平台上支持多少个文件描述符。在 Linux中,sizeof(fd_set)的结果是128 * 8 = FD_SETSIZE=1024)
select函数原型:
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
注释:
n
需要检查的文件描述符个数,n应该比是三组fd_set---(readfds,writefds,exceptfds)中最大数
更大,而不是实际文件描述符的总数。
readset
用来检查可读性的一组文件描述符。
writeset
用来检查可写性的一组文件描述符。
exceptset
用来检查意外状态的文件描述符。(注:错误并不是意外状态)
timeout
等待最长时间,如果timeout==NULL,则进入无限期等待,如果其中tv_sec和tv_usec都等于0, 则文件描述符
的状态不被影响,但函数并不挂起
返回值是返回响应操作的对应操作文件描述符的总数,且三组数据均在恰当位置被修改,只有响应操作的那一些没有修改。可用FD_ISSET宏来查找此操作符(参考上例子)。
当然如果我们把NULL指针作为fd_set传入的话,这就表示我们对这种操作的发生不感兴趣,但select() 还是会等待直到其发生或者超过等待时间,不过我想这样没什么意义吧。。
例子中还用到的linux时间操作函数,在上一篇日志中已经有详细说明,此就不多介绍了。
参考:
Linux下select调用的过程: 1.用户层应用程序调用select(),底层调用poll()) 2.核心层调用sys_select() ------> do_select() 最终调用文件描述符fd对应的struct file类型变量的struct file_operations *f_op的poll函数。poll指向的函数返回当前可否读写的信息。 1)如果当前可读写,返回读写信息。 2)如果当前不可读写,则阻塞进程,并等待驱动程序唤醒,重新调用poll函数,或超时返回。3.驱动需要实现poll函数。当驱动发现有数据可以读写时,通知核心层,核心层重新调用poll指向的函数查询信息。 poll_wait(filp,&wait_q,wait) // 此处将当前进程加入到等待队列中,但并不阻塞 在中断中使用wake_up_interruptible(&wait_q)唤醒等待队列 2011-02-2420:50:13