linux Select()系统调用

在网络程序中,一个进程同时处理多个文件描述符是很常见的情况。select()系统调用可以使进程检测同时等待的多个I/O设备,当没有设备准备好时,select()阻塞,其中任一设备准备好时,select()就返回。

select()的调用形式为:

#include<sys/select.h>

#include<sys/time.h>

intselect(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, conststruct timeval *timeout);

select的第一个参数是文件描述符集中要被检测的比特数,这个值必须至少比待检测的最大文件描述符大1;参数readfds指定了被读监控的文件描述符集;参数writefds指定了被写监控的文件描述符集;而参数exceptfds指定了被例外条件监控的文件描述符集。

参数timeout起了定时器的作用:到了指定的时间,无论是否有设备准备好,都返回调用。timeval的结构定义如下:

structtimeval{

longtv_sec; //表示几秒

longtv_usec; //表示几微妙

}

timeout取不同的值,该调用就表现不同的性质:

1.timeout为0,调用立即返回;

2.timeout为NULL,select()调用就阻塞,直到知道有文件描述符就绪;

3.timeout为正整数,就是一般的定时器。

select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。select的返回值有如下情况:

1.正常情况下返回就绪的文件描述符个数;

2.经过了timeout时长后仍无设备准备好,返回值为0;

3.如果select被某个信号中断,它将返回-1并设置errno为EINTR。

4.如果出错,返回-1并设置相应的errno。

系统提供了4个宏对描述符集进行操作:

#include<sys/select.h>

#include<sys/time.h>

voidFD_SET(int fd, fd_set *fdset);

voidFD_CLR(int fd, fd_set *fdset);

voidFD_ISSET(int fd, fd_set *fdset);

voidFD_ZERO(fd_set *fdset);

宏FD_SET设置文件描述符集fdset中对应于文件描述符fd的位(设置为1),宏FD_CLR清除文件描述符集fdset中对应于文件描述符fd的位(设置为0),宏FD_ZERO清除文件描述符集fdset中的所有位(既把所有位都设置为0)。使用这3个宏在调用select前设置描述符屏蔽位,在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。

过去,描述符集被作为一个整数位屏蔽码得到实现,但是这种实现对于多于32个的文件描述符将无法工作。描述符集现在通常用整数数组中的位域表示,数组元素的每一位对应一个文件描述符。例如,一个整数占32位,那么整数数组的第一个元素代表文件描述符0到31,数组的第二个元素代表文件描述符32到63,以此类推。宏FD_SET设置整数数组中对应于fd文件描述符的位为1,宏FD_CLR设置整数数组中对应于fd文件描述符的位为0,宏FD_ZERO设置整数数组中的所有位都为0。假设执行如下程序后:

#include<sys/select.h>

#include<sys/time.h>

fd_setreadset;

FD_ZERO(&readset);

FD_SET(5,&readset);

FD_SET(33,&readset);


select()函数与Linux驱动程序的关系

当用户调用select系统调用时,select系统调用会先调用poll_initwait(&table);,然后调用驱动程序中 struct file_operations下的fop->poll函数,在这个函数里应该调用poll_wait(),将current加到某个等待队列(这里调用poll_wait()),并检查是否有效,如果无效就调用schedule_timeout();去睡眠。事件发生后,schedule_timeout()回来,,调用fop->poll();,检查到可以运行,就调用poll_freewait(&table);从而完成select系统调用。重要的是fop->poll()里面要检查是否就绪,如果是,要返回相应标志。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值