JAVA - IO模型

Posted hpzhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA - IO模型相关的知识,希望对你有一定的参考价值。

本章内容

  1 同步,异步,阻塞,非阻塞的概念

  2 五种IO模型:阻塞式IO,非阻塞式IO,多路复用IO,信号驱动IO,异步IO 各自的特点

 

 

同步,异步,阻塞,非阻塞(注意:这里是从用户线程和内核层面来介绍概念的)

 

同步和异步(描述的是用户线程与内核的交互方式 - 消息的通信机制)

  1 同步 用户线程发起IO后需要等待

  2 异步 用户线程发起IO请求后仍然继续执行,当内核操作完成后会通知用户线程,或者调用用户线程注册的回调函数

 

阻塞和非阻塞(描述的是程序等待调用结果是的状态 - 调用者的状态)  

  1 阻塞 在调用结果返回之前,调用者的执行线程会挂起,线程不能做其它事情,只有等待结果返回才能往下执行

  2 非阻塞 IO操作被调用后立即返回调用者一个状态值,无需等待IO操作彻底完成

 

IO模型 

 

介绍

  操作系统为了安全,将内存空间分成了用户空间和内核空间,用户进程无法直接操作底层硬件,只能将请求提交给CPU,由CPU去执行

  进程(线程)将请求提交给CPU,等待CPU返回数据(这是一个两段式的过程)

    1 等待数据准备:内核从IO设备将数据拷至内存空间的Buffer中

    2 内核将数据从内部的Buffer中拷贝至进程空间 

  

  注意:内核在IO操作时,会为每一个IO设备维护一个Buffer,等待数据输入到Buffer,从Buffer复制到进程内存空间,都需要时间,根据等待模式可以分为:

    1 blocking IO 阻塞式IO (两段都阻塞)

    2 nonblocking IO 非阻塞式IO (第一段不阻塞,第二段阻塞)

    3 IO multiplexing IO复用 (两段都阻塞)

    4 signal driven IO 信号驱动IO (第一段不阻塞,第二段阻塞)

    5 asynchronus IO 异步IO (两段都不阻塞)

 

下面将对以上五种模型做一个详细的介绍

 

阻塞式IO

  1 用户线程在读写时阻塞,系统调用不返回调用结果并让当前线程一直阻塞,只有当该系统调用获得结果或者超时出错时才返回

  技术分享图片

 

  如图:

    1 recvfrom 发起系统调用,当内核无数据报准备好时,要等待数据准备 (第一段) 应用进程阻塞

    2 当内核数据准备好后,将数据拷贝至用户空间(第二段)应用进程阻塞  拷贝完成后,返回成功,让用户进程去处理数据包,此时阻塞结束,将控制权移交给应用进程

  2 缺点

    用户进程在IO过程中被阻塞,不能做任何事情,对CPU的资源利用率不高

 

非阻塞式IO

  1 用户线程不断发起IO请求,数据未到达前时系统返回一个状态值,数据到达后才真正读取数据(需要用户线程不断确定数据报是否已经准备好)

  技术分享图片

  如图:

    1 当用户进程recvfrom发起一个系统调用,内核无数据包准备好时会返回一个EWOULDBLOCK状态,当用户进程不知道内核有没有准备好数据,需要通过不断轮询的方式去确定数据报是否准备好(这个过程用户进程是非阻塞的)

    2 当内核准备好数据后,内核将数据拷贝至进程空间(用户进程阻塞)

  2 缺点

    用户进程每次请求IO都可以立即返回,但是为了拿到数据,需不断地轮询,无谓地消耗了大量CPU

 

IO多路复用(模式介绍不是很详细,将在后续BIO,NIO中进行详细介绍)

  1 用户先将需要进行IO操作的socket添加到select中,然后等待阻塞函数select返回,当数据到达后,socket被激活,select返回,用户线程就能接着发起read请求(注意:阻塞的是select)

    这里涉及到操作系统底层提供的 select,poll,epoll三种机制,这里举例为select(将在后续NIO中介绍此种模式的使用) 

  技术分享图片

 

  如图:

    I/O多路复用是通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作

  2 优点

    可以在单个线程/进程中处理更多的连接

    系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销 

 

信号驱动IO

  技术分享图片

  如图:

    1 先开启套接字的驱动式IO功能,并通过sigachtion系统调用安装一个信号处理函数,该系统调用立即返回,进程继续工作,当数据报准备好时,内核为该进程产生一个SIGIO信号 (第一段不阻塞)

    2 接收到信号后,再次发起系统调用,由内核将数据包拷贝至用户空间(第二段阻塞)

异步IO

  1 工作机制 告知内核启动某个操作,并让内核在整个操作完成后通知我们

  技术分享图片

 

  如图:

    1 应用进程发起系统调用,内核立即返回一个状态,此时进程继续执行

    2 当内核准备好数据,并将数据包拷贝至用户空间后,通知进程处理 (两段都不阻塞)

 

总结:

  1 阻塞式IO:用户进程发起系统调用,阻塞用户进程,内核处理数据报,当两段全部处理完成后,返回成功指示,再由用户进程去处理数据报

  2 非阻塞式IO:用户进程发起系统调用,当内核数据报未准备好时,返回一个状态给用户进程,用户进程继续执行,未阻塞,但需要发起轮询,不断地询问内核数据报是否准备好,当发现数据报已准备好时,阻塞用户进程,由内核将数据报拷贝至用户空间,拷贝完成后,返回成功指示,由用户进程去处理

  3 多路复用IO:用户进程将IO请求注册到select中,用户进程继续执行,select发起系统调用,内核做数据准备,当内核准备好数据时,返回相应用户进程的可读指示,用户进程再发起系统调用,用户进程阻塞,内核将数据报拷贝至用户空间,拷贝完成后,返回成功指示,由用户进程去处理

  4 信号驱动IO:用户进程发起系统调用,当内核数据报未准备好时,返回一个状态给用户进程,用户进程继续执行,未阻塞,当内核准备好数据时,通过信号通知用户进程,用户进程再发起系统调用,用户进程阻塞,内核将数据报拷贝至用户空间,拷贝完成后,返回成功指示,由用户进程去处理

  5 异步IO:用户进程发起系统调用,当内核数据包未准备好是,返回一个状态给用户进程,用户进程继续执行,未阻塞,当内核准备好数据,并将数据拷贝至用户空间后,通知用户进程去直接处理数据报  

 

以上是关于JAVA - IO模型的主要内容,如果未能解决你的问题,请参考以下文章

Java IO模型:BIONIOAIO

JAVA - IO模型

网络通信模型(IO模型)学习摘要

java IO 模型--快速分清 同步|阻塞

java常用的IO模型

《JDK源码分析》IO模型详解:第一章:IO模型演进(JAVA 小虚竹)