五种常见IO模型

前言

大家好,我是周周,目前就职于国内短视频某厂的BUG攻城狮一枚。

如果文章对你有帮助,记得关注、点赞、收藏,一键三连哦,你的支持将成为我最大的动力。

文章目录

    • 前言
    • 1 概述
      • 1.1 什么是 IO
      • 1.2 什么是缓冲区
      • 1.3 阻塞和非阻塞
      • 1.4 同步和异步
    • 2 五种 IO 模型
      • 2.1 同步阻塞 IO
      • 2.2 同步非阻塞 IO
      • 2.3 IO 多路复用
      • 2.4 异步 IO
      • 2.5 信号驱动 IO

1 概述

服务端高并发 IO 编程往往要求的性能都非常高,一般情况下需要选用高性能的 IO 模型,比如我们日常使用的 Redis 就采用了 IO 多路复用以提高自身性能。本文将从操作系统、网络、Java 等多个方面聊聊几种常见的 IO 模型。

1.1 什么是 IO

IO 全程 Input/Output,即数据的读取(接收)或写入(发送)操作,针对不同的数据存储媒介,大致可以分为网络 IO 和磁盘 IO 两种。

而在 Linux 系统中,为了保证系统安全,操作系统将虚拟内存划分为内核空间用户空间两部分。因此用户进程无法直接操作IO设备资源,需要通过系统调用完成对应的IO操作。

即此时一个完整的 IO 操作将经历一下两个阶段:用户空间 <-> 内核空间 <-> 设备空间

五种常见IO模型_第1张图片

1.2 什么是缓冲区

应用层的 IO 操作基本都是依赖操作系统提供的 read 和 write 两大系统调用实现。但由于计算机外部设备(磁盘、网络)与内存、CPU 的读写速度相差过大,若直接读写涉及操作系统中断,因此为了减少 OS 频繁中断导致的性能损耗和提高吞吐量,引入了缓冲区的概念。

根据内存空间的不同,又可分为内核缓冲区进程缓冲区

操作系统会对内核缓冲区进行监控,等待缓冲区达到一定数量的时候,再进行 IO 设备的中断处理,集中执行物理设备的实际 IO 操作,通过这种机制来提升系统的性能。至于具体什么时候执行系统中断(包括读中断、写中断)则由操作系统的内核来决定,应用程序不需要关心。

1.3 阻塞和非阻塞

阻塞 IO指的是需要内核 IO 操作彻底完成后才返回到用户空间执行用户程序的操作指令。

非阻塞 IO(Non-Blocking IO,NIO) 指的是用户进程不需要等待内核 IO 操作彻底完成,即可返回用户空间执行后续指令。与此同时,内核会立即返回给用户一个 IO 状态值。

阻塞是指用户进程一直在等待,而不能做别的事情;非阻塞是指用户进程获得内核返回的状态值就返回自己的空间,可以去做别的事情。

1.4 同步和异步

同步 IO是指用户空间(进程或者线程)是主动发起 IO 请求的一方,系统内核是被动接收方。

异步 IO则反过来,系统内核是主动发起 IO 请求的一方,用户空间是被动接收方。

同步和异步最大的区别就是被调用方的执行方式和返回时机。同步指的是被调用方做完事情之后再返回,异步指的是被调用方先返回,然后再做事情,做完之后再想办法通知调用方(此时数据已 ready,调用方可以直接使用)。

阻塞和非阻塞关注的是调用方进程状态,而同步与异步更关注调用双方进程通信方式。

2 五种 IO 模型

2.1 同步阻塞 IO

同步阻塞IO(Blocking IO) 指的是用户进程(或线程)主动发起,需要等待内核 IO 操作彻底完成后才返回到用户空间的 IO 操作。在 IO 操作过程中,发起 IO 请求的用户进程处于阻塞状态。

五种常见IO模型_第2张图片

2.2 同步非阻塞 IO

同步非阻塞IO(Non-Blocking IO,NIO) 指的是用户进程主动发起,不需要等待内核 IO 操作彻底完成就能立即返回用户空间的 IO 操作。在 IO 操作过程中,发起 IO 请求的用户进程处于非阻塞状态。

五种常见IO模型_第3张图片

1)当数据 Ready 之后,用户线程仍然会进入阻塞状态,直到数据复制完成,并不是绝对的非阻塞。

2)NIO 实时性好,内核态数据没有 Ready 会立即返回,但频繁的轮询内核,会占用大量的 CPU 资源,降低效率。

2.3 IO 多路复用

IO 多路复用(IO Multiplexing) 实际上就解决了 NIO 中的频繁轮询 CPU 的问题,并且引入一种新的 select 系统调用。

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

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

五种常见IO模型_第4张图片

2.4 异步 IO

异步IO(Asynchronous IO,AIO) 指的是用户空间的线程变成被动接收者,而内核空间成为主动调用者。在异步 IO 模型中,当用户线程收到通知时,数据已经被内核读取完毕并放在用户缓冲区内,内核在 IO 完成后通知用户线程直接使用即可。而此处说的 AIO 通常是一种异步非阻塞 IO

五种常见IO模型_第5张图片

2.5 信号驱动 IO

当进程发起一个 IO 操作,会向内核注册一个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用 IO 读取数据。

信号驱动 IO 不同于 AIO 的是依旧存在阻塞状态,即用户进程获取到数据就绪信号后阻塞进行 IO 操作。

你可能感兴趣的:(Java,java,Netty,NIO,网络)