后台核心技术开发与应用实践读书笔记(七)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40028201/article/details/89516463

后台核心技术开发与应用实践读书笔记(七)

第4章 网络IO模型

7.0 IO操作

​ 不同的IO设备有不同的特点

  1. 同步IO与异步IO

    • 同步:必须等到IO操作完成后控制权才返回给用户进程
    • 异步:无需等IO操作完成,就将控制权返回给用户进程
  2. 当一个IO操作发生时(如read)会涉及两个对象

    • 调用这个IO的进程
    • 系统内核

    当一个read操作发生时,会经历两个阶段:

    • 等待数据准备
    • 将数据从内核拷贝到进程中

7.1 4 种网络IO模型

​ 分别是:阻塞IO模型、非阻塞IO模型、多路复用IO模型、异步IO模型;《Unix网络编程》中多了一种 信号驱动型IO模型。以上五种,除了异步IO模型是异步的,其他的都是同步的

以下是各种IO模型的示意图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  1. 阻塞IO与分阻塞IO的区别

    扫描二维码关注公众号,回复: 6027479 查看本文章
    • 阻塞IO操作需要彻底完成后才能返回到用户空间
    • 非阻塞IO操作被调用后会立即给用户状态值,不需要等IO操作彻底完成
  2. 阻塞IO

    几乎所有的IO接口都是阻塞的

    • 缺点 :在调用send()的同时,线程处于阻塞状态,在此期间线程无法执行任何运算和响应任何网络请求
    • 解决方案:服务端使用多线程(多进程)。这样做的目的让每个连接都拥有独立的线程(进程),注意
      • 进程的开销远远大于线程,若要同时为较多的客户端提供服务,使用多线程
      • 如果单个服务执行体需要消耗较多的CPU资源(大规模或长时间的数据运算或数据访问),使用较为安全的进程
    • 对于多线程模型,如果同时响应成百上千路的连接请求,则无论多线程或多进程都会严重占据系统资源,降低响应系统对外界的响应效率,多进程多线程也容易进入假死状态
      • 线程池:降低创建和销毁线程的频率
      • 连接池:维持连接的缓存池,尽量重用已有的连接,降低创建和关闭连接的频率
      • 要根据响应规模来调整“池”的大小
      • 多线程模型可以应对小规模,对于大规模(成千上万),多线程模型遇到瓶颈,可以使用非阻塞模型
  3. 非阻塞IO

    ​ 在Linux下可以设置socket使得IO变为非阻塞状态

    1. 过程

      非阻塞IO需要应用进程不断的主动询问kernel数据是否准备好。如果返回错误(没准备好)用户进程再发送read操作

    2. recv()调用开销

      服务器线程可以通过循环调用recv接口,可以在单个线程内实现对所有连接的数据接收工作,但不推荐

      • 循环调用该接口大幅度占用CPU使用率
      • 可以使用下面是说道的多路复用模式(一次检测多个连接是否活跃)
  4. 多路IO复用模型(事件驱动IO)

    1. 原理
      • 函数(如select)会不断地轮询所负责的所有socket,当某个socket有数据了,就通知用户进程
      • 调用select整个进程会阻塞,内核会监视所有的select负责的socket,有一个准备好了,就返回
    2. 优缺点
      • 使用了两个系统调用(select和recvfrom),阻塞IO只有后面一个系统调用
      • 优势在于可以处理多个连接,不是更快,而是更多
      • 所以如果连接数不是很多,select/poll的优势可能不如多线程阻塞IO的WebServer性能更好
  5. 异步IO模型

    1. 过程
      • 一方面用户进程发起read操作后,立刻去做其他的事情
      • 另一方面,内核收到一个异步的read请求操作后,首先会立刻返回,不会对用户进程造成任何阻塞。然后内核会等待数据准备完成,然后将数据拷贝到用户内存中,这一切完成后,内核会给用户进程发送一个信号,表示read操作已经完成
    2. 非阻塞IO与异步IO的区别
      • 非阻塞IO中,虽然大部分时间都不会被阻塞,但是需要进程主动检查,并且数据准备完成后,也需要进程调用recvfrom来将进程去主动检查
      • 异步IO不同,更像是用户进程将整个IO操作交给了他人(内核)完成,然后内核做完后发信号通知,在这个期间,用户进程不需要检查IO操作状态,也不需要准点拷贝数据

7.2 select

  1. 基本原理

    select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

  2. 优缺点

    1. 优点
      • 良好的跨平台
    2. 缺点
      • 在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效率的降低
      • 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。

7.3 poll

  1. 基本原理:poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间
  2. 优缺点
    • 相对于select没有了最大连接数的限制,因为是链表来存储的
    • 大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
    • poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

7.4 epoll

​ epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有 描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事 件表中,这样在用户空间和内核空间的copy只需一次。

  1. 基本原理:

    epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就绪态,并且只会通知一次。还有一个特点是,epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知。

  2. 优点

    1. 没有最大并发连接的限制`,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
    2. 效率提升,不是轮询的方式,不会随着FD数目的增加效率下降
    3. 只有活跃可用的FD才会调用callback函数;即Epoll最大的优点就在于它只管你“活跃”的连接
    4. 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销

select、poll、epoll的区别

​ select、poll、 epoll都是多路IO复用的机制

具体区别上面已经说明了,以下简要总结

  1. select与poll
    1. poll没有最大文件描述符限制
    2. poll在大数目描述符的速度更快
    3. select可监控的文件描述是固定的1024/2048
    4. select的可移植性更好
    5. select超时有更好的精度,poll较差
  2. epoll优点
    1. 有FD限制,但是很大
    2. 不是轮询,效率高,只有活跃的才调用回调函数
    3. 内存拷贝

参考博客

  1. IO多路复用之select、poll、epoll详解

猜你喜欢

转载自blog.csdn.net/qq_40028201/article/details/89516463