一文搞懂五种iO模型

2023年 7月 19日 37.2k 0

关键词:

poll epoll select channel Input output
AIO BIO NIO 多路复用 多线程 进程
用户态 内核态 字节流 字符流

IO种类分为: 阻塞IO,非阻塞IO,IO多路复用,信号驱动IO,异步IO 共5种

IO 全程 Input/Output,针对不同的数据存储媒介,大致可以分为网络 IO 和磁盘 IO 两种。一个完整的 IO 操作将经历一下两个阶段:用户空间 内核空间 设备空间

IO具体是什么操作?

干了什么事?

为什么有5种类型?

5种类型分别解决了什么问题?

只用阻塞IO可以吗?

IO牵扯到具体的指令有哪些?

IO读操作

真正的IO读操作:外部设备的数据经过总线进入RAM中系统空间的系统缓冲区。

用户看到的假IO操作:用户调用IO接口函数,从系统缓冲区读取数据读到自己的缓冲区或某个变量中

IO写操作

真正的IO写操作:RAM中系统空间的系统缓冲区中的数据经过总线进入外部设备。

用户看到的假IO操作:用户调用IO接口函数,把自己的某个变量或者自己的缓冲区写入系统缓冲区。

实际IO过程

用户调用IO接口函数后会询问内核缓冲区是否有目标数据,如果没有内核缓冲区在外部设备准备好后接收IO接口传来的数据,内核缓冲区读取外部设备的数据的过程是IO过程。

阻塞IO:

​ 需要等待内核 IO 操作彻底完成后才返回到用户空间的 IO 操作。在 IO 操作过程中,发起 IO 请求的用户进程处于阻塞状态。

模型如下:

在这里插入图片描述

在这里插入图片描述

同步非阻塞IO

​ 不需要等待内核 IO 操作彻底完成就能立即返回用户空间的 IO 操作。在 IO 操作过程中,发起 IO 请求的用户进程处于非阻塞状态。

模型:

在这里插入图片描述

在这里插入图片描述

IO多路复用

解决了 NIO 中的频繁轮询 CPU 的问题,并且引入一种新的 select 系统调用。

复用 IO 的基本思路就是通过 slect 调用来监控多 fd(文件描述符),来达到不必为每个 fd 创建一个对应的监控线程的目的,从而减少线程资源创建的开销。一旦某个描述符就绪(一般是内核缓冲区可读/可写),内核就能够将文件描述符的就绪状态返回给用户进程(或者线程),用户空间可以根据文件描述符的就绪状态进行相应的 IO 系统调用。

Linux中IO复用的实现方式主要有Select,Poll和Epoll:

Select:注册IO、阻塞扫描,监听的IO最大连接数不能多于FD_ SIZE(1024)。
Poll:原理和Select相似,没有数量限制,但IO数量大,扫描线性性能下降。
Epoll :事件驱动不阻塞,mmap实现内核与用户空间的消息传递,数量很大,Linux2.6后内核支持。

IO 多路复用(IO Multiplexing)属于一种经典的 Reactor 模式实现,有时也称为异步阻塞 IO。

poll和epoll的区别:

在Java中,epoll和poll是用于实现I/O多路复用的机制,但它们在底层实现和使用方式上有一些区别。

  1.poll是传统的I/O多路复用机制,而epoll是Linux特有的高性能I/O多路复用机制。

  2.poll使用的是轮询方式,它通过遍历文件描述符集合来检查是否有事件发生,效率相对较低。

  3.epoll使用的是事件通知方式,它通过注册文件描述符和事件,并在事件发生时立即通知应用程序,避免了不必要的轮询,提高了效率。

在这里插入图片描述

在这里插入图片描述

信号驱动IO

信号驱动IO是异步阻塞IO,不需要等待IO的过程,但是从内核读取数据受到阻塞

在这里插入图片描述

在这里插入图片描述

异步IO

异步IO从图上看很像信号驱动IO,但是实际差别很大,异步IO指异步非阻塞IO。异步IO不需要建立信号处理程序,再把IO接口函数放进去。异步IO只需要调用IO接口函数,在里面加入数据处理函数即可,并且不存在任何阻塞

在这里插入图片描述

在这里插入图片描述

总结:

对比:

在这里插入图片描述

在这里插入图片描述

实际的多线程模型:

根据博客参考,实际的多线程模型有很多。在《操作系统》中介绍较少,理解起来并不是很全面。

多对一模型:进程下的多个用户级线程对应着一个核心级线程,这也就是《操作系统》中说这句话的默认情景。操作系统知道核心线程,不知到用户线程,当用户线程阻塞时会认为是核心级线程阻塞,那么操作系统会调度另一个核心级线程执行。

一对一模型:进程下的每个用户级线程对应着属于自己的核心级线程。当一个线程被阻塞时,操作系统能够让另一个核心级线程对应的用户线程继续执行。缺点是每个用户线程都会创建一个核心级线程,未免有些浪费。

多对多模型:进程下的每个用户级线程对应着多个核心级线程,每个核心级线程也对应着多个用户级线程。这个模型能完成前两个模型能完成的任务,但是实现复杂。

线程与进程的区别与联系

  • 线程是轻量级的进程
  • 线程没有独立的地址空间(内存空间)
  • 线程是由进程创建的(寄生在进程)
  • 一个进程可以拥有多个线程(这就是我们常说的多线程编程)
  • 相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论