目录

一、select函数

1、select的作用:

2、select的用法:

3、select的内核实现:


一、select函数

1、select的作用:

select可以对文件描述符fd进行监听。通常我们把需要监听的fd放入到一个集合fd_set,select就可以对集合fd_set中的数据是否发生可读、可写、异常等行为进行监听,以达到在同一个进程中实时处理多个IO的目的。

2、select的用法:

函数原型:
int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
参数说明:
maxfdp:集合中所有文件描述符的范围,需设置为所有文件描述符中的最大值加1。
readfds:要进行监听的是否可以读文件的文件描述符集合。
writefds:要进行监听的是否可以写文件的文件描述符集合。
errorfds:要进行监听的是否发生异常的文件描述符集合。
timeval:select的超时时间,它可以使select处于三种状态:
1、若将NULL以形参传入,即不传入时间结构,就是将select至于阻塞状态,一定要等到监视的文件描述符集合中某个文件描述符发生变化为止。
2、若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否发生变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值。
3、timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回,否则在超时后不管怎样一定返回。
返回值:
>0:表示被监视的文件描述符有变化。
-1:表示select出错。
0:表示超时。

select函数的使用还涉及到一些对fd_set操作的函数,这里说明如下:

fd_set:可以理解为一个集合,这个集合中存放的时文件描述符fd。

FD_ZERO:
用法:FD_ZERO(fd_set *);
作用:用来清空fd_set集合,即让fd_set集合不再包含任何文件句柄。
FD_SET:
用法:FD_SET(int, fd_set *);
作用:用来将一个给定的文件描述符加入集合之中。
FD_CLR:
用法:FD_CLR(int, fd_set *);
作用:用来将一个给定的文件描述符从集合中删除。
FD_ISSET:
用法:FD_ISSET(int, fd_set *);
作用:检测fd在fdset集合中的状态是否发生变化,当检测到fd状态变化时返回真,否则,返回假(也可以认为集合中指定的文件描述符是否可以读写)。

此处应插入一个实例。

3、select的内核实现:

这里有一篇博客比较详细的讲解了select的内核实现,大家可以参考一下,我这边主要对自己关心的部分进行总结。

https://blog.csdn.net/qq_37058442/article/details/78004507

总的来说,select函数的调用时需要底层驱动程序的支持,驱动程序需要实现fops中的poll函数。select通过每个设备文件对应的poll函数提供的信息判断当前是否有资源可用(如可读或可写),如果有的话则返回可用资源的文件描述符个数,没有的话则睡眠(timeval设置为NULL时),等待有资源变为可用时再被唤醒继续执行。

select在内核中的调用是这样的:sys_select->core_sys_select->do_select。

在do_select中,select会循环遍历它所监测的fd_set内的所有文件描述符对应的驱动程序的poll函数。驱动程序提供的poll函数首先会将调用select的用户进程插入到该设备驱动对应资源的等待队列(如读/写等待队列)(即poll_wait),然后返回一个bitmask告诉select当前资源哪些可用。当select循环遍历完所有fd_set内指定的文件描述符对应的poll函数后,如果没有一个资源可用(即没有一个文件可供操作),则select让该进程睡眠,一直等到有资源可用为止,进程被唤醒(或者timeout)继续往下执行。

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐