详解磁盘IO、网络IO、零拷贝IO、BIO、NIO、AIO、IO多路复用(select、poll、epoll)

本文详细介绍了I/O模型,包括磁盘IO、网络IO、IO中断、DMA、零拷贝IO,以及BIO、NIO、AIO和IO多路复用(select、poll、epoll)的工作原理。通过这些内容,读者可以理解各种I/O模式的差异,以及它们在不同场景下的适用性。
摘要由CSDN通过智能技术生成

文章很长,但是很用心!

1. 什么是I/O

在计算机操作系统中,所谓的I/O就是输入(Input)和输出(Output),也可以理解为读(Read)和写(Write),针对不同的对象,I/O模式可以划分为磁盘IO模型和网络IO模型。

IO操作会涉及到用户空间和内核空间的转换,先来理解以下规则:

  • 内存空间分为用户空间和内核空间,也称为用户缓冲区和用户缓冲区
  • 用户的应用程序不能直接操作内核空间,需要将数据从内核空间拷贝到用户空间才能使用
  • 无论是read操作,还是write操作,都只能在内核空间里执行
  • 磁盘IO和网络IO请求加载到内存的数据都是先放在内核空间的

再来看看所谓的读(Read)和写(Write)操作:

  • 读操作:操作系统检查内核缓冲区有没有需要的数据,如果内核缓冲区已经有需要的数据了,那么就直接把内核空间的数据copy到用户空间,供用户的应用程序使用。如果内核缓冲区没有需要的数据,对于磁盘IO,直接从磁盘中读取到内核缓冲区(这个过程可以不需要cpu参与)。而对于网络IO,应用程序需要等待客户端发送数据,如果客户端还没有发送数据,对应的应用程序将会被阻塞,直到客户端发送了数据,该应用程序才会被唤醒,从Socket协议找中读取客户端发送的数据到内核空间,然后把内核空间的数据copy到用户空间,供应用程序使用。
  • 写操作:用户的应用程序将数据从用户空间copy到内核空间的缓冲区中(如果用户空间没有相应的数据,则需要从磁盘—>内核缓冲区—>用户缓冲区依次读取),这时对用户程序来说写操作就已经完成,至于什么时候再写到磁盘或通过网络发送出去,由操作系统决定。除非应用程序显示地调用了sync命令,立即把数据写入磁盘,或执行flush()方法,通过网络把数据发送出去。
  • 绝大多数磁盘IO和网络IO的读写操作都是上述过程,除了后面要讲到的零拷贝IO。

2. 磁盘IO

磁盘IO的流程如下图所示:

(1)读操作

当应用程序调用read()方法时,操作系统检查内核缓冲区中是否存在需要的数据,如果存在,那么就直接把内核空间的数据copy到用户空间,供用户的应用程序使用。如果内核缓冲区没有需要的数据,通过通过DMA方式(一种IO设备控制方式,下面会讲解)从磁盘中读取数据到内核缓冲区,然后由CPU控制,把内核空间的数据copy到用户空间。

这个过程会涉及到两次缓冲区copy,第一次是从磁盘的缓冲区到内核缓冲区,第二次是从内核缓冲区到用户缓冲区(或应用缓冲区),第一次是cpu的copy,第二次是DMA的copy。

(2)写操作

当应用程序调用write()方法时,应用程序将数据从用户空间copy到内核空间的缓冲区中(如果用户空间没有相应的数据,则需要从磁盘—>内核缓冲区—>用户缓冲区依次读取),这时对用户程序来说写操作就已经完成,至于什么时候把数据再写到磁盘(从内核缓冲区到磁盘的写操作也由DMA控制,不需要cpu参与),由操作系统决定。除非应用程序显示地调用了sync命令,立即把数据写入磁盘。

如果应用程序没准备好写的数据,则必须先从磁盘读取数据才能执行写操作,这时会涉及到四次缓冲区的copy,第一次是从磁盘的缓冲区到内核缓冲区,第二次是从内核缓冲区到用户缓冲区,第三次是从用户缓冲区到内核缓冲区,第四次是从内核缓冲区写回到磁盘。前两次是为了读,后两次是为了写。这其中有两次cpu拷贝,两次DMA copy。

(3)磁盘IO的延时

为了读或写,磁头必须能移动到所指定的磁道上,并等待所指定的扇区的开始位置旋转到磁头下,然后再开始读或写数据。磁盘IO的延时分成以下三部分:

  • 寻道时间:把磁头移动到指定磁道上所经历的时间
  • 旋转延迟时间 :指定扇区移动到磁头下面所经历的时间
  • 传输时间 :数据的传输时间(数据读出或写入的时间)

img

3. 网络IO

网络IO的流程如下:

(1)读操作

网络IO的既可以从物理磁盘中读数据,也可以从socket中读数据(从网卡中获取)。当从物理磁盘中读数据的时候,其流程和磁盘IO的读操作一样。当从socket中读数据,应用程序需要等待客户端发送数据,如果客户端还没有发送数据,对应的应用程序将会被阻塞,直到客户端发送了数据,该应用程序才会被唤醒,从Socket协议找中读取客户端发送的数据到内核空间(这个过程也由DMA控制),然后把内核空间的数据copy到用户空间,供应用程序使用。

(2)写操作

为了简化描述,我们假设网络IO的数据从磁盘中获取,读写操作的流程如下:

  • 当应用程序调用read()方法时,通过DMA方式将数据从磁盘拷贝到内核缓冲区
  • 由cpu控制,将内核缓冲区的数据拷贝到用户空间的缓冲区中,供应用程序使用
  • 当应用程序调用write()方法时,cpu会把用户缓冲区中的数据copy到内核缓冲区的Socket Buffer中
  • 最后通过DMA方式将内核空间中的Socket Buffer拷贝到Socket协议栈(即网卡设备)中传输。

网络IO的写操作也有四次缓冲区的copy,第一次是从磁盘缓冲区到内核缓冲区(由cpu控制),第二次是内核缓冲区到用户缓冲区(DMA控制),第三次是用户缓冲区到内核缓冲区的Socket Buffer(由cpu控制),第四次是从内核缓冲区的Socket Buffer到网卡设备(由DMA控制)。四次缓冲区的copy工作两次由cpu控制,两次由DMA控制。

(3)网络IO的延时

网络IO主要延时是由:服务器响应延时+带宽限制+网络延时+跳转路由延时+本地接收延时 决定。一般为几十到几千毫秒,受环境影响较大。所以,一般来说,网络IO延时要大于磁盘IO延时。

4. IO中断与DMA

以前传统的IO读写是通过中断由cpu控制的,为了减少CPU对I/O的干预,引入了直接存储器访问方式(DMA)方式。在DMA方式下,数据的传送是在DMA的控制下完成的,不需要cpu干预,所以CPU和I/O设备可以并行工作,提高了效率。现在来看看它们各自的原理:

(1)IO中断原理

  1. 用户进程通过read等系统调用接口向操作系统(即CPU)发出IO请求,请求读取数据到自己的用户内存缓冲区中,然后该进程进入阻塞状态
  2. 操作系统收到用户进程的请求后,进一步将IO请求发送给磁盘。
  3. 磁盘驱动器收到内核的IO请求后,把数据读取到自己的缓冲区中,此时不占用CPU。当磁盘的缓冲区被读满之后,向内核发起中断信号告知自己缓冲区已满。
  4. 内核收到磁盘发来的中断信号,使用CPU将磁盘缓冲区中的数据copy到内核缓冲区中
  5. 如果内核缓冲区的数据少于用户申请读的数据,则重复步骤2、3、4,直到内核缓冲区的数据符合用户的要求为止。
  6. 内核缓冲区的数据已经符合用户的要求,CPU停止向磁盘IO请求。
  7. CPU将数据从内核缓冲区拷贝到用户缓冲区,同时从系统调用中返回。
  8. 用户进程读取到数据后继续执行原来的任务。

中断IO缺点:每次IO请求都需要CPU多次参与。

(2)DMA原理

  1. 用户进程通过read等系统调用接口向操作系统(即CPU)发出IO请求,请求读取数据到自己的用户内存缓冲区中,然后该进程进入阻塞状态
  2. 操作系统收到用户进程的请求后,进一步将IO请求发送给DMA,然后CPU就可以去干别的事了
  3. DMA将IO请求转发给磁盘。
  4. 磁盘驱动器收到内核的IO请求后,把数据读取到自己的缓冲区中,当磁盘的缓冲区被读满后,向DMA发起中断信号告知自己缓冲区已满。
  5. DMA收到磁盘驱动器的信号,将磁盘缓存中的数据copy到内核缓冲区中,此时不占用CPU(IO中断这里是占用CPU的)
  6. 如果内核缓冲区的数据少于用户申请读的数据,则重复步骤3、4、5,直到内核缓冲区的数据符合用户的要求为止。
  7. 内核缓冲区的数据已经符合用户的要求,DMA停止向磁盘IO请求
  8. DMA发送中断信号给CPU。
  9. CPU收到DMA的信号,知道数据已经准备好,于是将数据从内核空间copy到用户空间,系统调用返回。
  10. 用户进程读取到数据后继续执行原来的任务。

跟IO中断模式相比,DMA模式下,DMA就是CPU的一个代理,它负责了一部分的拷贝工作,从而减轻了CPU的负担

需要注意的是,DMA承担的工作是从磁盘的缓冲区到内核缓冲区或网卡设备到内核的soket buffer的拷贝工作,以及内

### 回答1: 在Java中,网络IO的实现方式有BIONIOAIO三种。 1. BIO(Blocking I/O) BIO是Java最早的一种网络IO实现方式。它通过阻塞式的方式来进行网络IO操作,即一个线程在进行IO操作时会一直阻塞,直到IO操作完成。这种方式的优点是编程简单易懂,但缺点是并发性能较差,不能满足高并发的需求。 2. NIO(Non-blocking I/O) NIO是Java在1.4版本中引入的一种新的网络IO实现方式。NIO的核心是Selector(选择器),它能够监控多个通道的状态,当某个通道有数据可读或可写时,Selector会通知相应的线程进行处理。NIO采用非阻塞式的方式进行IO操作,可以支持更高的并发性能。但是,NIO编程难度较大,需要掌握较多的概念和技巧。 3. AIO(Asynchronous I/O) AIO是Java在1.7版本中引入的一种新的网络IO实现方式。AIO采用异步的方式进行IO操作,即一个线程在进行IO操作时不需要一直阻塞,而是可以继续执行其他任务,当IO操作完成后再由系统通知线程进行处理。AIO可以支持更高的并发性能,并且编程模型比NIO更加简单。但是,AIO的兼容性不如NIO,需要在操作系统和JVM等多个方面进行支持。 ### 回答2: 在Java中,网络IO可以通过不同的方式实现,这些方式包括BIO(阻塞IO)、NIO(非阻塞IO)和AIO(异步IO)。 BIO是最早的实现方式,也是最简单直观的方式。它的特点是使用阻塞模式,即当一个线程在进行IO操作时,其他线程必须等待IO操作完成才能继续执行。在BIO中,每个连接都需要一个独立的线程来处理,这可能导致服务器资源浪费,无法满足高并发的需求。 NIO是在Java 1.4中引入的新IO模型,相较于BIO,它具有更高的并发处理能力。NIO使用了多路复用器(Selector)来管理多个连接,一个线程可以通过一个选择器同时处理多个连接的IO操作,从而避免了每个连接都需要一个独立线程的问题。 AIO是在Java 1.7中引入的新IO模型,也被称为NIO.2。AIO是基于事件和回调机制的,它的特点是IO操作后不需要对应的线程进行阻塞等待,而是通过回调方式来通知IO操作已经完成。AIO适合处理连接数较多且连接时间较长的场景,例如聊天服务器。 综上所述,BIONIOAIO是Java中实现网络IO的三种方式。BIO适用于连接数较小的场景,NIO适用于连接数较多但连接时间较短的场景,而AIO适用于连接数较多且连接时间较长的场景。选择适合的IO模型能够提高服务器的并发处理能力和效率。 ### 回答3: JAVA中有三种主要的网络IO实现方式,分别是BIO(Blocking IO)、NIO(Non-blocking IO)和AIO(Asynchronous IO)。 BIO是JAVA IO最传统的模型,采用阻塞方式进行IO操作。在BIO模型中,每个连接都需要一个独立的线程来处理,当有大量的连接时,就需要大量线程,会导致性能下降。 NIO是JAVA IO的改进版本,引入了通道(Channel)和缓冲区(Buffer)的概念。NIO采用非阻塞方式进行IO操作,可以提高IO的效率。在NIO模型中,一个线程可以处理多个连接,通过选择器(Selector)来监听多个通道的事件,当有事件发生时,线程可以进行处理。 AIO是JAVA NIO的进一步改进,引入了异步通道(AsynchronousChannel)和回调机制。AIO采用异步方式进行IO操作,可以在IO操作完成之后再通知线程进行处理,而不需要线程一直等待IO操作完成。AIO适用于高并发的场景,可以大大提高系统的吞吐量和性能。 总结来说,BIO适用于连接数较少且业务处理较简单的场景;NIO适用于连接数较多但每个连接的并发处理量不大的场景;AIO适用于连接数较多且每个连接的并发处理量大的场景。选择合适的IO模型可以根据业务需求和实际场景进行选择,来提高系统的性能和并发能力。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雷恩Layne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值