I/O复用之select

select函数注意事项

#include<sys/select.h>
#include<sys/time.h>
int select (int maxfd,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval * timeout)

关于I/O复用之select函数,函数原型和头文件已经给出,具体参数含义就不再赘述。不太熟悉的可以参考UNIX网络编程卷一(socket编程)这本书。本文主要讲下在使用过程中需要注意的事项。

一、返回值

select返回值为int整型,如果监听的多个文件描述符就绪(即你所关心的可读或可写或异常),则返回就绪的描述符个数。如果设定了timeout时间,则如果时间到达之前并没有文件描述符就绪,则返回0。如果当时间未到达或未设置时间(最后一个参数为NULL),此时监听项还未就绪,select理应阻塞,但由于此时有信号过来,则此时任何阻塞的系统调用都将被唤醒,此时,select返回-1.

二、time值

1、如果上述timeout为NULL,则select会阻塞直至监听项就绪。
2、如果timeout中的秒和微妙都设置为0,则此时select检查完描述符后立即返回,这就是轮询。
3、time值在大多数情况下在函数返回时不会被select修改,但真的是根据操作系统不同而不同的。笔者所用的centos7就会被select修改成该函数返回时剩余的秒数,因此,为了代码的健壮性,建议大家在每一次调用select之前都对timeout重新赋值。

三、 fd_set变化

调用select函数之后,并不是把发生变化的文件描述符集中到一起,而是通过观察作为监视对象fd_set变量的变化找出发生变化的文件描述符,因此,需要遍历整个fd_set数组,时间复杂度为O(n),当监听项数目很大,而活跃连接又很少,此时效率很低。况且,fd_set的size一般有所限制,默认为1024.
当select函数调用完成后,向其传递的fd_set变量将发生变化。描述符集内的任何与未就绪描述符对应的位均清成0.
怎样理解这句话呢,请看下图:
在这里插入图片描述

此时,select所监听的项每一次都就绪,所以对应的位仍为1,但如果在时间结束后,还未就绪,则对应的位会被清成0!
如下图:

在这里插入图片描述
所以,我们在每一次调用select的时候,仍需要通过FD_SET宏,在fd_set所指向的变量中注册监听项的文件描述符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值