• 服务器(I/O)之多路转接


    五种IO模型

    1、阻塞等待:在内核将数据准备好之前,系统调用会一直等待。所有的套接字,默认都是阻塞方式。

    2、非阻塞等待:如果内核没有将数据准备好,系统调用仍然会返回,并且会返回EWUOLDBLOCK或者EAGAIN错误码。

    3、信号驱动:内核将数据准备好的时候,使用SIGIO信号通知应用程序进行IO操作。

    4、多路转接(多路转接):能够同时等待多个文件句柄的就绪状态。

    5、异步IO:由内核在数据拷贝完成时,通知应用程序。(而信号驱动是告诉应用程序什么时候可以开始拷贝数据)。

    前四种都属于同步IO,第五种属于异步IO。同步IO和异步IO,区别在于同步IO会参与IO结果的获取的过程。而异步IO则是不会参与IO结果获取的过程,直接拿到最终的IO结果。

    IO的本质就是等和拷贝数据。也就是说没有数据的时候,就需要等待数据,当有数据的时候,再将数据拷贝走。而高效的IO,要达到高效,关键在于减少等的比重才能达到效果。在上述的五种IO模型中,多路转接的方式,一次等待多个文件描述符,在某种意义上等的效率更高,也就是说一次等通知多个就绪能够进行拷贝的文件描述符。

    I/O多路转接之select

    select系统调用是用来让我们的程序监视多个文件描述符的状态变化的; 程序会停在select这里等待,直到被监视的文件描述符有一个或多个发生了状态改变;

    函数原型

    参数解释:

    nfds表示最大文件描述符+1。

    readfdswritefdsexceptfds(位图结构)分别需要检测的可读文件描述符集合、可写文件描述符集合和异常文件描述符集合。

    timeout表示设置select()的等待时间。(timeout取值(NULL、0、特定时间)

    NULL表示阻塞等待,

    0则表示仅检测描述符集合的状态,然后立即返回,

    特定时间值表示select的等待时间)。

    操作fd_set位图结构的接口

    函数返回值

    执行成功---->则返回文件描述符状态已改变的个数

    如果返回0---->代表在描述词状态改变前已超过timeout时间,没有返回

    当有错误发生时则---->返回-1,错误原因存于errno,此时参数readfds,writefds, exceptfds和timeout的 值变成不可预测。

    select特点

    可监控的文件描述符个数取决与sizeof(fd_set)的值. 我这边服务器上sizeof(fd_set)=512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096。

    将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd。         一是用于再select 返回后,array作为源数据和fd_set进行FD_ISSET判断。

           二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。

    select缺点

    每次调用select, 都需要手动设置fd集合, 从接口使用角度来说也非常不便.

    每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

    每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

    select支持的文件描述符数量太小

    I/O多路转接之poll

    函数原型

    参数解释:

    fds是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返回的事件集合.

    其中events和revents的取值可以为如下。比如POLLIN或者POLLOUT但是某一位为1的宏,可以设置进events或者内核设置进revents中。

    nfds表示fds数组的长度

    timeout表示poll函数的超时时间, 单位是毫秒(ms).

    返回值

    返回值  <  0, 表示出错;

    返回值  =  0, 表示poll函数等待超时;

    返回值  >  0, 表示poll由于监听的文件描述符就绪而返回

    poll的优点

    不同与select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现

            pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式. 接口使用比 select更方便

            poll并没有最大数量限制 (但是数量过大后性能也是会下降,因为需要轮询的检测就绪的事件).

    poll的缺点

    在监听的文件句柄增多时

    和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符.

    每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中.

    同时连接的大量客户端在一时刻可能只有很少的处于就绪状态, 因此随着监视的描述符数量的增长, 其效率也会线性下降.

    I/O多路转接之epoll

    函数原型

    创建epoll句柄

    epoll的函数与select和poll的函数不同,epoll的函数有三个分别独立完成各自功能。

    参数size表示所创建的epoll模型,最大能监听文件句柄的数目。

    返回值

    success -----> return 正数。fail -----> return -1

    将要监控的文件描述符进行注册

    参数:

            epfd表示我们所创建的epoll模型的文件句柄。

            op表示关心添加的文件句柄的什么行为。用三个宏来表示。

                    EPOLL_CTL_ADD :注册新的fd到epfd中;

                    EPOLL_CTL_MOD :修改已经注册的fd的监听事件;

                    EPOLL_CTL_DEL :从epfd中删除一个fd;

            fd表示我们需要添加关心的文件句柄

            event表示我们关心添加的文件句柄的什么事件。epoll_event结构体如下:

                    

                    其中events可以是一下宏的集合

    返回值:

    success -----> return 0。fail -----> return -1

    等待文件描述符就绪

    参数:

            epfd表示我们所创建的epoll模型的文件句柄。

            events表示系统监听到文件句柄的事件就绪并拷贝至用户的结构体数组

            maxevents表示events数组的大小。

            timeout表示超时时间(毫秒,0会立即返回,-1是永久阻塞)。

    返回值:

            success ----> return 就绪的文件描述符的个数。

            超时  ----->  return 0

            fail  ----> return -1

    多路转接的工作原理

    首先,epoll的使用是一个单进程,因此我们可以通过进程找到对应的epoll句柄。

    select和poll的原理:忽略其中的1、2和文件句柄,就单单看3。当外设将数据通过驱动刷新到对应文件句柄中,该文件句柄就就绪了。但是使用者需要轮询遍历3这个队列。

    epoll的原理:现在我们需要将上图看作一个整体,epoll模型中存在一个红黑树存放关心的文件句柄,并带有回调函数。当外设将数据通过驱动刷新到对应文件句柄中,该文件句柄就就绪了。然后调用其回调函数,将3中就绪的文件句柄添加到2中的就绪队列中。也就是说,epoll不用再轮询遍历3这个队列了,直接遍历2这个就绪队列就能拿到所有就绪的文件句柄了。

            其次,epoll中维护着红黑树、就绪队列等数据结构,在Linux中都是交由文件管理的。着就是为什么要创建epoll模型,也就是epoll文件句柄了。

            epoll中的三个函数epoll_create、epoll_ctl、epoll_wait,epoll_create函数负责创建句柄,并初始化队列3的大小。epoll_ctl函数负责向红黑树中添加关心的文件句柄,并注册回调函数。epoll_wait函数则是遍历就绪队列2,拿到就绪的文件句柄。

  • 相关阅读:
    uni-app实现图片预览
    苹果新专利:用AR眼镜来控制iPhone屏幕输出,保护隐私
    Netty 学习(二):服务端与客户端通信
    The First项目报告:Stargate Finance重塑跨链金融的未来
    bert 环境搭建之Pytorch&Transformer 安装
    第3章 Linux网络编程 01. 网络结构模式
    【C语言】sizeof和strlen的区别
    薯队长写了一篇笔记草稿,请你帮忙输出最后内容。
    通信算法之八十:信道均衡-MMSE 定点化
    DELL R730服务器开机报错:[XXX] usb 1-1-port4: disabled by hub (EMI?), re-enabling...
  • 原文地址:https://blog.csdn.net/qq_45576085/article/details/132636173