前言
我们在开发中使用的中间件大多都有使用I/O。如果我们想真正了解这些中间件,我们还是很有必要来学习一下I/O操作。接下来我会用图示结合文字来总结一下几种I/O模型。
一 BIO是什么?
BIO(同步阻塞):当某个事件或者任务在执行过程中,它发出一个请求操作,但是由于操作需要的条件不存在/不满足,那么就会一直在那等待,直至条件满足;
(如:你有一个10L的桶,你去水池接水 当你没有接满的时候 你不能去做任何事情 只能等到 水接满后才能离开去做其他事情。)
图示:
用户线程通过调用read发起 IO读操作,由用户空间转到内核空间,内核等待数据到达缓冲区后将数据拷贝到用户空间完成read结果。
如果调用read后,数据没有到达缓冲区 那么用户线程一直会阻塞,直到内核返回结果。
二、NIO是什么?
NIO(同步非阻塞):不管是否满足条件,都会立马返回结果。如果没有满足的话,那么就不间断的循环重试,但我们整个应用不会阻塞。
(如:你有一个10L的桶,你去水池接水 你可以去做其他事情,但需要每隔一会 去看一看有没有接满 。)
用户线程通过调用read发起 IO读操作,数据还没有到达缓冲区内则返回error不会进行阻塞,若下次收到read后发现数据到达缓冲区则拷贝到用户空间 返回结果。
三、AIO是什么?
AIO(异步IO/多路复用之Proactor模式): 指定缓存区注册到内核中,当数据包到达后 拷贝到指定的内存区后通知用户线程,并完成读操作。
(如:你有一个10L的桶,你去水池接水 你可以去做其他事情,等满了以后有人去通知你,并帮你拎回来。)
用户线程调用系统异步IO指定用户缓存区注册到内核,此时用户线程不在关心任何东西, 内核等待数据到达后拷贝到用户指定的缓存区将数据分发后通知用户线程,完成读取
四、I/O多路复用是什么?
IO multiplexing(I/O多路复用):说起多路复用可能比较陌生,但是说select/poll/epoll大概就都能明白了。
select/epoll的好是可以同时处理多个网络连接的IO。它的基本原理就是function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户线程。
当用户线程调用了select,那么整个线程会被阻塞,而同时 内核会“监控”所有负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户线程再调用read操作,将数据拷贝到用户线程。
select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。在单个连接上效果还不如以上几种。
结合这个模型 猜想一下 为什么Redis 使用的是单线程模型呢?
五、多路复用之Reactor模式是什么?
Reactor模式:在IO操作中,用户线程会给对应的socket注册函数,然后用户线程会继续执行,当内核数据包到达时会通知用户线程可以读取了,用户线程接收到后,调用read 进行操作。
通过Reactor方式.将用户线程IO操作工作交给Reactor 循环处理.用户线程注册事件之后可以继续执行其他工作(异步),而Reactor中线程动用内核中的Select函数检查socket状态,当socket被激活.通知对应的用户线程进行数据读取.
总结
以上就是今天要讲的内容,本文仅仅简单介绍了操作系统I/O模型,想学好JAVA NIO 或Netty 框架 我们首先要把操作系统I/O理解明白 以便更好地去写代码。
如: JAVA NIO 是将操作系统那些IO进行了封装,以便我们调用更好地去使用呢。Redis为什么使用单线程他又是利用了那些I/O模型呢等等等…