• select函数介绍


             目录

    1、 第一个参数 nfds

    2、 第二个参数 readfds

    (1) 第二个参数的作用

    (2) 第二个参数的类型

    (3) 如何设置 fd_set 类型

    (4) 内核最多可以关注多少个fd

    3、第三、第四个参数

    4、第五个参数 timeout

    (1) timeval类型

    (2) 第五个参数timeout的作用

    (3) 第五个参数timeout的特点

    5、函数返回值


    一个完整的IO过程 = 等待数据就绪 + 拷贝数据。以recv接口函数为例,recv函数先阻塞等待接收缓冲区里的数据就绪,数据就绪以后再把数据从接收缓冲区拷贝到上层。这里要重点介绍的是等待方式,select模型就是其中一种等待方式,而实现select模型的关键就是select接口函数

    select函数其实是在底层不断去轮询检查 fd 是否处于就绪状态,一旦有一个 fd 处于就绪状态,就通知上层。select函数的作用仅仅是负责等待没有所谓的读写功能。下面是select函数的函数声明。

    1、 第一个参数 nfds

    代表 一组fd中的最大值+1。因为select函数每次可以检测多个 fd 是否有读写事件就绪,而这里的nfds就代表这些 fd 中的最大值max_fd + 1。

    加1的原因是,select底层是通过 for循环: for(int i=0;i < nfds;i++)  轮询检测的,这里用的 '<' 而并非 '≤',所以 i 最大可以是 max_fd

    2、 第二个参数 readfds

    (1) 第二个参数的作用

    我们在使用select函数的时候,一是希望select函数可以帮我们关注一批fd的读事件是否就绪;二是如果有哪个 fd 的读事件就绪,希望select函数可以反馈给我。第二个参数就起到这个作用。

    (2) 第二个参数的类型

    这是一个输入输出型参数,参数类型是 fd_set 是位图类型,可以看作是 fd 集合。输入的时候,假设你希望内核帮你关注 fd = 0 、1、2的读事件就绪情况,此时就可以输入 0111;输出的时候,假设是fd = 0的读事件就绪了,内核会返回的位图是 0001

    (3) 如何设置 fd_set 类型

    虽然我们可以使用原生的位图类型,即手动设置fd 集合,但是这样未免过于麻烦,OS给我们提供了设置 fd_set 类型的接口。

    • FD_CLR            —— 将某个文件描述符从集合中去除
    • FD_ISSET         —— 判断某个文件描述符是否在集合中
    • FD_SET            —— 将文件描述符加入到集合中
    • FD_ZERO         —— 清空集合

    (4) 内核最多可以关注多少个fd

    底层既然是以位图形式管理fd,那么每个fd所占用的空间只是 一个bit,从下面的图可以了解到,fd的大小是 128 个字节 = 1024 bit,因此,每个fd_set类型的集合最多可以帮我们关注 1024 个文件描述符。

    3、第三、第四个参数

    第三个参数表示 写事件集合,即你希望select模型帮你关注哪些fd上的写事件是否就绪;

    第四个参数表示 异常事件集合,即你希望select模型帮你关注哪些fd上的异常事件是否发生。

    注意:这两个参数的设置方式可以参考第二个参数的设置方式

    4、第五个参数 timeout

    我们可以通过第五个参数设置select的等待方式,在说明之前,先了解第五个参数的数据类型。

    (1) timeval类型

    timeval是一个结构体类型,用于设置时间长短,结构体声明如下:

    第一个成员表示秒,第二个成员表示毫秒

    1. timeval* timeout = {5,0}; //设置的时间是5.0s
    2. timeval* timeout = {5,1}; //设置的时间是5s + 1ms = 5.001s

    (2) 第五个参数timeout的作用

    我们可以通过第五个参数设置select的等待方式,阻塞、非阻塞或者 阻塞非阻塞混搭

    • timeout = NULL:阻塞式轮询每一个fd,只要事件不就绪,select函数就不返回 
    • timeout = {0 , 0}:非阻塞式轮询每个fd,如果事件不就绪,select函数立马返回 0(返回解析详见下面)
    • timeout = {5 , 0}:先阻塞等待5s,这5s内不会返回;5s以后,如果事件没有就绪,select函数立马返回

    (3) 第五个参数timeout的特点

    第五个参数timeout也是一个输入输出型参数,输入的时候表示用户希望select函数阻塞多长时间;输出的时候表示 距离 结束阻塞等待 还有多长时间。

    5、函数返回值

    select返回值有三种:

    • 事件就绪的时候,返回 事件就绪的fd 的个数,此时ret > 0
    • 事件没有就绪的时候,如果是非阻塞模式,此时 ret = 0,表明当前 事件就绪的fd 的个数为0
    • 调用出错的时候,ret = -1
  • 相关阅读:
    6.终于了解volatile的原理和使用方法了
    HTML+CSS+JS制作一个迅雷看看电影网页设计实例 ,排版整洁,内容丰富,主题鲜明,简单的网页制作期末作业
    Power BI 矩阵总计放表第一列
    线性代数学习笔记7-5:复习——正交、投影、行列式、特征值
    .netCore用DispatchProxy实现动态代理
    使用del语句删除名称对引用计数的影响
    V10服务器安装virt-manage
    RESTful API是什么?看完你整个人都通透了
    计算机毕业设计基于Python实现的高校学生生活信息交互平台
    用script去做前端html表格分页/排序
  • 原文地址:https://blog.csdn.net/challenglistic/article/details/127093922