NIO

Nov 2, 2020 · 1 min read

在讲NIO的原理之前,首先掌握几个基础概念,内核缓冲进程缓冲区

进程缓冲区:存在于用户程序空间,由应用程序进行管理。

内核缓冲区:存在于内核空间,由操作系统的内核进行管理,当我们进行IO操作的时候,无论是硬盘还是网络,内核缓冲去的数据什么时候写入到磁盘,什么时候写入到网卡,是由内核来决定,应用程序不需要感知。

Alt text

四种主要的IO模型

什么是阻塞和非阻塞? 阻塞和非阻塞是针对于进程在访问数据时,根据IO操作的就绪状态而采取的不同方式,简单来说是一种读取或写入操作函数的实现方式,阻塞方式下读取或写入函数将一直等待。非阻塞方式下,读取和写入函数会立即返回一个状态值。

什么是同步和异步? 同步和异步是针对应用程序和内核的交互而言的,同步是指用户进程触发IO操作并等待或轮询的查看IO操作是否就绪,异步是指用户进程触发IO操作以后便开始做自己的事情,当IO操作完成时会得到通知,换句话说异步的特点就是通知。

IO模型可以分为四种:同步阻塞、同步非阻塞、异步阻塞、异步非阻塞

同步阻塞IO(Blocking IO)

阻塞IO,指的是需要内核IO操作彻底完成后,才返回到用户空间,执行用户的操作。阻塞指的是用户空间程序的执行状态,用户空间程序需等到IO操作彻底完成。传统的IO模型都是同步阻塞IO,其中同步是指用户应用程序主动向内核发起IO请求。

同步非阻塞IO(Non-blocking IO)

非阻塞IO,指的是用户程序不需要等待内核IO操作完成后,内核立即返回给用户一个状态值,用户空间无需等到内核的IO操作彻底完成,可以立即返回用户空间,执行用户的操作,处于非阻塞的状态。

异步阻塞(Asynchronous Blocking IO)

异步IO,指的是用户空间与内核空间的调用方式反过来。用户空间线程是变成被动接受的,内核空间是主动调用者。

同步阻塞IO是指用户进程在发起一个IO操作后必须等待IO操作完成,只有当真正完成了IO操作后用户进程才能运行。

同步非阻塞IO是指用户进程发起一个IO操作后立即返回,程序也就可以做其他事情。但是用户进程需要不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。

NIO

NIO是同步非阻塞IO

同步是进行IO操作的时候是由应用程序主动发起向内核发起IO请求。 非阻塞表示IO操作不会阻塞当前进程的执行。 如果和避免NIO中的论 NIO采用了IO多路复用技术,因为NIO是同步IO,所以采用的是多路复用中的Reactor模式。

NIO的select实际上是使用的epoll来实现的,EPollSelectorImpl extend SelectorImpl。

Epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的电平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

Acceptor注册Selector并监听accept事件 当客户端连接后会触发accept事件 服务器构建对应的Channel并在其上注册Selector,用于监听读写事件。 当发生读写事件后进行相应的读写处理。