• linux 学习 day09 多路转接select、poll、epoll


    五中 IO 模型

    阻塞IO
    • 阻塞IO:在内核将数据准备好之前,系统调用会一直等待,所有的套接字,默认都是阻塞方式。
      在这里插入图片描述
    非阻塞IO
    • 非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符,这个过程称为轮训. 这对CPU来说是较大的浪费,只有特定的场景下才使用。
      在这里插入图片描述
    信号驱动IO
    • 内核将数据准备好的时候,使用SIGIO信号通知应用程序进行IO操作。
      在这里插入图片描述
    IO多路转接
    • 从流程上看类似于阻塞IO,但是实际最核心在于IO多路转接能够同时等待多个文件描述符就绪状态。
      在这里插入图片描述
    异步IO
    • 友内核在数据拷贝完成时,通知应用程序(而信号驱动是高职应用程序合适可以开始拷贝数据)。
      在这里插入图片描述
    任何IO过程,都只包含两个步骤,第一是等待,第二是拷贝。而且在实际的应用场景中,等待消耗的时间往往远远高于拷贝的时间。 让IO更高效,最核心的办法就是让等待的时间尽量少。

    同步通信 vs 异步通信(synchronous communication/asynchronous communication)

    • 同步和异步关注的是消息通信机制
    • 所为同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了;换句话说,就是主动调用者主动等待这个调用的结果。
    • 异步则是相反,调用在发出后,这个调用就直接返回了,所以没有返回结果;换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果;而是在调用发出后,被调用者通过状态来通知调用者,或者通过回调函数处理这个调用。

    阻塞 vs 非阻塞

    阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。

    • 阻塞调用时指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才返回。
    • 非阻塞调用指不能立刻返回得到结果之前,该调用不会阻塞当前线程。

    非阻塞IO

    fcntl

    一个文件描述符,默认都是阻塞IO。
    函数原型如下
    在这里插入图片描述
    传入的 cmd 的值不同,后面追加的参数也不相同。
    fcntl 函数有5种功能:

    • 复制一个现有的文件描述符(cmd = F_DUPFD).
    • 获得/设置文件描述符标记(cmd = F_GETFD/F_SETFD).
    • 获得/设置文件状态标记(cmd = F_GETFL/F_SETFL).
    • 获得/设置异步IO所有权(cmd = F_GETOWN/SETOWN).
    • 获得/设置记录锁(cmd = F_GETLK、F_SETLK/F_SETLKW).

    基于fcntl,实现一个SetNoBlock函数,将文件描述符设置为非阻塞.

    在这里插入图片描述
    在这里插入图片描述

    IO 多路转接

    select

    • select 的函数原型如下
      #include
      在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    select 执行过程

    在这里插入图片描述

    socket 就绪条件
    读就绪

    在这里插入图片描述

    写就绪

    在这里插入图片描述

    异常就绪

    在这里插入图片描述

    select 特点

    在这里插入图片描述
    注意: fd_set的大小可以调整,可能涉及到重新编译内核.

    select 缺点

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    poll

    poll 函数接口
    在这里插入图片描述
    在这里插入图片描述

    poll 优点

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

    • pollfd 结构包含了要监视的fd和发生的event,不再声依永select 参数-值传递方式。 还是用比select更方便。
    • poll并没有最大数量限制(但是数量过大后性能也会下降)。
    poll 缺点

    在这里插入图片描述

    在这里插入图片描述

    epoll

    epoll 友三个相关的系统调用
    在这里插入图片描述
    在这里插入图片描述
    struct epoll_event 结构如下
    在这里插入图片描述
    在这里插入图片描述

    epoll 工作原理

    在这里插入图片描述
    在这里插入图片描述

    • 每个epoll对象都有一个独立的eventpoll结构体,用于存放通过epool_ctl方法想epoll对象中添加进来的事件。
    • 这些事件都会挂载在红黑树中,如此重复添加的事件就可以通过红黑树而高效的识别出来。
    • 而所有添加的epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当响应事件发生时会调用这个回调方法。
    • 这个会回调方法在内核中叫 ep_epoll_callback,它会将繁盛的事件添加到rdlist双向链表中。
    • 在epoll中,对于每一个事件,都会建立一个epitem结构体。

    在这里插入图片描述

    epoll 使用过程

    在这里插入图片描述

    epoll 的优点 vs select

    在这里插入图片描述

    epoll 工作方式

    epoll 有 2 中工作方式-水平触发(LT) 和边缘触发(ET)

    水平触发Level Triggered 工作模式

    在这里插入图片描述

    边缘触发Edge Triggered 工作模式

    在这里插入图片描述

    LT vs ET

    在这里插入图片描述

    ET模式和非阻塞文件描述符

    使用 ET 模式的 epoll, 需要将文件描述设置为非阻塞. 这个不是接口上的要求, 而是 “工程实践” 上的要求.
    假设这样的场景: 服务器接受到一个10k的请求, 会向客户端返回一个应答数据. 如果客户端收不到应答, 不会发送第二个10k请求.

    在这里插入图片描述
    如果服务端写的代码是阻塞式的read, 并且一次只 read 1k 数据的话(read不能保证一次就把所有的数据都读出来,参考 man 手册的说明, 可能被信号打断), 剩下的9k数据就会待在缓冲区中.
    在这里插入图片描述
    此时由于 epoll 是ET模式, 并不会认为文件描述符读就绪. epoll_wait 就不会再次返回. 剩下的 9k 数据会一直在缓冲区中. 直到下一次客户端再给服务器写数据. epoll_wait 才能返回。
    在这里插入图片描述
    在这里插入图片描述

    epoll 使用场景

    在这里插入图片描述

    epoll中的惊群问题

    参考网址 http://blog.csdn.net/fsmiy/article/details/36873357

    epoll 实例

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    随机数漫谈
    试从多个方面比较电路交换、报文交换和分组交换的主要优缺点?
    恒压频比开环控制系统Matlab/Simulink仿真分析(SPWM控制方式)
    OneFlow源码解析:算子指令在虚拟机中的执行
    07【MyBatis连接池与事务管理】
    Java中的SQL注入简易分析
    Spring——Spring基础介绍
    快手订单导出
    解决vue-cli node-sass安装不成功问题
    APK构建过程-命令行编译
  • 原文地址:https://blog.csdn.net/m0_51262652/article/details/126584309