IO流模型

BIO,NIO,AIO的区别

BIO同步阻塞式IO Blocking IO

就是我们将平常使用的传统IO,它的特点是模式简单,使用方便。每个客户端的Socket连接请求,都会有线程与之对应。没有分配到线程的连接会被阻塞或拒绝。连接越多,线程越多,当没有数据交互时,线程会等待,造成资源浪费

NIO同步非阻塞IO New IO

是传统IO的升级版,客户端和服务器通过Channel(通道)通讯,实现了多路复用。服务器保存一个Socket连接列表。然后对列表进行轮询,有操作就调用对应方法,没有就跳过。如果某个端口的连接已经中断,则调用对应的方法关闭该端口。充分提高服务器的资源利用率。

再具体实现IO请求操作的时候再用多个线程去处理,一个请求是一个线程。每个线程包含一个Selector对象,他相当于一个通道管理器,可以实现在一个线程中处理多个通道目的,减少线程的创建数量

一个远程连接对应一个channel,数据的读写通过buffer均在一个channel内完成,数据的读写时非阻塞的。

注册通道后,需要为该通道注册感兴趣事件(创建连接,接受数据,读数据,写数据)。selector线程需要采用轮训的方式调用selector的select函数,知道所有的注册通道有兴趣事件发生,否则一直阻塞

Selector :允许单线程处理多个连接Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。要使用Selector,得向Selector注册Channel,然后调用他的select方法,这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子入有新连接接进来,数据接收等。

Channel:基本所有的IO在NIO上都从一个Channel开始,Channel有点像流,数据可以从channel读到buffer,也可以从buffer读到channel

buffer:缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松的使用内存块,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变换情况,Channel提供从文件,网络读取数据的渠道,但是读取或者写入的数据都必须经由Buffer。每次传输数据都会发送一块一块的数据,增加了IO的效率

AIO异步非阻塞IO Asynchronous IO

是NIO的升级版,也叫NIO2,实现了异步非阻塞IO异步IO的操作基于时间和回调机制。AIO是异步非阻塞IO,相比NIO更进一步,进程读取数据时只负责发送跟接收指令,数据的准备工作完全由操作系统来处理。

IO操作流程

对于一个IO而言,从磁盘,网络读取数据,他会涉及到两个系统对象,一个是调用这个IO的process,另一个就是系统内核

  1. 发起IO请求
  2. 将数据从磁盘或网络拷贝到操作系统OS内核buffer(内核缓存),输出则相反
  3. 将操作系统内核数据拷贝到用户进程(如JVM缓存),输出则相反
  4. 结束IO操作

5种IO的模型

1.阻塞IO模式(同步阻塞式)在这里插入图片描述

进程发起IO操作调用后,进程被阻塞,转到内核空间处理,这个歌IO处理完后返回进程,操作成功则获取数据

进程阻塞挂起不消耗cpu,及时响应每个操作,实现难度低,开发应用容易,适合并发量小的网络应用开发

不适合并发量大的应用,因为一个请求IO会阻塞进程,所以得为每一个请求分配一个处理进程,即使响应,系统开销大

总结:阻塞IO就是当调用读取书哈桉树(比如read),这个函数不马上返回结果,而是阻塞当前进程,知道数据被废止到用户进程空间或是超出时才解除阻塞,并马上返回结果

2.非阻塞IO模型(同步阻塞式)

  1. 当用户进程发出read操作时,如果kernel中的数据还没有准备好;
  2. 那么它并不会block用户进程,而是立刻返回一个error,从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果;
  3. 用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call;
  4. 那么它马上就将数据拷贝到了用户内存,然后返回。

典型应用:socket的非阻塞的方式(设置为NONBLOCK)

特点:进程轮询(重复)调用,小号cpu组员,实现难度低,开发应用相对阻塞IO模式较难,并发量较小,不需要及时响应的网络应用开发;

总结:在非阻塞IO种,在用户调用read方法后,进程没有被阻塞。内核会立马返回数据给进程,这个数据可能是error提示,也可能是最终的结果,想要得到最终的结果,就需要用户进程主动的多次调用read方法在这里插入图片描述

进程:好了没? 内核:没好!

过了一些时间,进程:好了没? 内核:没好!!

又过了一些时间,进程:好了没? 内核:好了!!!

3.IO复用模型(同步非阻塞式)

  1. 当用户进程调用了select,那么整个进程会被block;
  2. ​而同时,kernel会“监视”所有select负责的socket;
  3. 当任何一个socket中的数据准备好了,select就会返回;
  4. 这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。

它不会对内存进行轮询操作,当内核数据准备完毕,以事件通知机制告知应用进程已经准备好了,在此之前,应用进程可以忙其他的工作,从而减少对性能的影响。通过多路IO复用,能使得一个进程同时处理多路IO,提升服务器吞吐量。

典型应用:select、poll、epoll三种方案(Linux中IO复用的实现方式);Java NIO。

特点: 专一进程解决多个进程IO的阻塞问题,性能好;Reactor模式; 实现、开发应用难度较大; 适用高并发服务应用开发:一个进程(线程)响应多个请求;

总结:在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为非阻塞,但是,如上图所示,整个用户的process其实是一直被阻塞的。只不过process是被select这个函数阻塞,而不是被socket IO给阻塞。

在这里插入图片描述

很多进程对select说,这是我的需求,我去作别的事情了(非阻塞),并纷纷将IO请求提交给select。select说好,然后再IO操作成功之后叫醒(返回结果)进程。

select,select和epoll两种模式的区别:

 select

select最大优势使用户可以在一个线程内同时处理多个IO请求,用户可以注册多个socket,然后不断调用select读取被激活的socket,线程可能会发出多次请求。可达到同一个县城内同时处理多个IO请求。

缺点:

  • 智能监控1024个线程
  • 不安全,
  • 每次调用select,都需要把fd_set集合从用户态拷贝到内核态,如果fd_set集合很大时这个开销也很大

poll:

poll的机制与select类似,与select在本质上没有多大差别。poll相较于select只解决了最大连接数的问题,即poll没有最大文件描述符的限制。

epoll:

select主动唤醒线程,返回结果,线程不会发出请求。

不会像服务器问询链接(将连接从用户态复制句柄数据结构到内核态)节省了大量资源,可以支持更高的并发连接

epoll设计和实现与select完全不同,会在linux内核中申请一个简易的文件系统(B+树)把原先的select/poll调用分成了3部分

1.调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源)

2.调用epoll_ct向epoll对象中添加这100万个连接的套接字

3.调用epoll_wait收集发生的事件的连接

如此一来,要实现上面说是的场景,只需要在进程启动时创建一个epoll对象,然后在需要的时候向这个epoll对象中添加或是删除连接。同事,epoll_wait的效率很高,因为调用时,并没有一股脑向操作系统复制这100万个连接的句柄数据,内核也不需要去遍历全部的连接

在这里插入图片描述

信号驱动式IO模型(同步非阻塞)

同步和异步的区别在于数据从内核空间拷贝到用户空间是否由用户线程完成,这里又分为同步阻塞,同步非阻塞

同步阻塞:此时线程一个线程维护一个连接,该线程完成数据读写到处理的所有过程,数据读写时线程还是被阻塞的

同步非阻塞:非阻塞的意思是用户线程发出请求后,请求不会阻塞当前用户线程,不过用户线程还是要不断去主动判断数据是否准备ok了,此时还是会阻塞等待内核复制数据到用户进程,它与同步BIO的区别是使用一个连接全程等待

特点:回调机制,实现、开发应用难度大; ​​​​​​在这里插入图片描述

 异步IO模型(异步非阻塞)

 当进程发起一个IO操作,进程返回(不阻塞),但也不能返回果结;内核把整个IO处理完后,会通知进程结果并执行回调函数(用户提供的callback)。此时数据已经从内核拷贝到用户空间,用户宣传只需要对数据进行处理即可,不需要关注读写,用户不需要等待内核对数据的复制操作。如果IO操作成功则进程直接获取到数据。期间程序不阻塞,会一直执行

典型应用:JAVA7 AIO

特点: 不会阻塞,数据一步到位:proactor模式;非常适合高新能高并发应用

需要操作系统底层的支持在这里插入图片描述

五种IO模型的比较

在这里插入图片描述

阻塞IO和非阻塞IO的区别在哪?

  • 阻塞会一直阻塞住对应的进程知道操作完成,
  • 而非阻塞IO在内核再还没有准备数据的情况下会立即返回。
  • 阻塞和非阻塞关注的是进程在等待调用结果的状态
  • 阻塞是指调用返回结果之前,当前进程会被挂起,调用进程只有在得到结果才会返回
  • 非阻塞调用指不能立刻获取结果,该调用不会阻塞当前进程

同步IO与异步IO的区别

同步主动调用recvfrom来讲数据拷贝到用户内存中

异步进程将整个IO操作交给了他人(内核)完成,然后他人昨晚发送信号通知,在此期间,用户进程不需要去检查IO操作的状态,也不需要主动拷贝数据

信号驱动式IO和异步IO的区别?

信号驱动IO与异步IO的区别在于启用异步IO意味着通知内核启动某个IO操作、并让内核在整个操作(包括数据从内核复制到用户缓冲区)完成时通知我们

异步IO是由内核通知我们IO操作何时完成、即实际的IO操作也是异步的、信号驱动IO是由内核通知我们何时可以启动一个IO操作、这个IO操作由用户自定义的信号函数来实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值