精华内容
下载资源
问答
  • IO模型

    多人点赞 2021-04-23 13:50:22
    文章目录IO模型Linux的五种IO模型同步阻塞IO模型(Blocking IO)同步非阻塞IO模型(nonblocking IO)IO 多路复用(IO multiplexing)信号驱动式IO(signal-driven IO)异步IO模型(asynchronous IO)JAVA的IO模型BIO--同步阻塞...

    IO模型

    Linux的五种IO模型

    五种IO模型包括:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO

    简单介绍一下几个linux函数

    recvfrom
    Linux系统提供给用户用于接收网络IO的系统接口。从套接字上接收一个消息,可同时应用于面向连接和无连接的套接字。

    成功完成后,这两个调用都将返回消息的长度。 如果消息太长而无法容纳在提供的缓冲区中,则多余的字节可能会被丢弃,此时,返回值则取决于接收消息的套接字类型。

    如果套接字上没有可用的消息,则接收调用将阻塞等待消息到达,除非套接字是非阻塞的,在这种情况下,将返回值-1且外部变量errno设置为EAGAIN 或EWOULDBLOCK。

    select
    select系统调用允许程序同时在多个底层文件描述符上,等待输入的到达或输出的完成。以数组形式存储文件描述符,64位机器默认2048个。当有数据准备好时,无法感知具体是哪个流OK了,所以需要一个一个的遍历,函数的时间复杂度为O(n)

    poll
    链表形式存储文件描述符,没有长度限制。本质与select相同,函数的时间复杂度也为O(n)

    epoll
    是基于事件驱动的,如果某个流准备好了,会以事件通知,知道具体是哪个流,因此不需要遍历,函数的时间复杂度为O(1)

    sigaction
    用于设置对信号的处理方式,也可检验对某信号的预设处理方式。Linux使用SIGIO信号来实现IO异步通知机制。

    select poll epoll
    操作方式 遍历 遍历 回调
    底层实现 数组 链表 红黑树
    IO效率 每次调用都进行线性遍历,时间复杂度为O(n) 每次调用都进行线性遍历,时间复杂度为O(n) 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到readyList里面,时间复杂度O(1)
    最大连接数 1024(x86)或2048(x64) 无上限 无上限
    fd拷贝 每次调用select,都需要把fd集合从用户态拷贝到内核态 每次调用poll,都需要把fd集合从用户态拷贝到内核态 调用epoll_ctl时拷贝进内核并保存,之后每次epoll_wait不拷贝

    同步&异步

    同步和异步是针对应用程序和内核交互而言的,也可理解为被**被调用者(操作系统)**的角度来说。
    同步是用户进程触发IO操作并等待或轮询的去查看是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知,需要CPU支持

    阻塞&非阻塞

    阻塞和非阻塞是针对于进程在访问数据的时候,也可理解为**调用者(程序)**角度来说。根据IO操作的就绪状态来采取的不同的方式。
    阻塞方式下读取或写入方法将一直等待,而非阻塞方式下读取或写入方法会立即返回一个状态值。

    同步阻塞IO模型(Blocking IO)

    场景描述:我和女友点完餐后,不知道什么时候能做好,只好坐在餐厅里面等,直到做好,然后吃完才离开。女友本想还和我一起逛街的,但是不知道饭能什么时候做好,只好和我一起在餐厅等,而不能去逛街,直到吃完饭才能去逛街,中间等待做饭的时间浪费掉了。

    同步阻塞 IO 模型是最常用的一个模型,也是最简单的模型。在linux中,默认情况下所有的socket都是blocking

    阻塞IO的执行过程是进程进行系统调用等待内核将数据准备好并复制到用户态缓冲区后,进程放弃使用CPU一直阻塞在此,直到数据准备好。

    同步非阻塞IO模型(nonblocking IO)

    场景描述:我女友不甘心白白在这等,又想去逛商场,又担心饭好了。所以我们逛一会,回来询问服务员饭好了没有,来来回回好多次,饭都还没吃都快累死了啦。这就是非阻塞。需要不断的询问,是否准备好了。

    每隔一段时间应用程序就去询问内核是否有数据准备好。如果就绪,就进行拷贝操作;如果未就绪,就不阻塞程序,内核直接返回未就绪的返回值,等待用户程序下一个轮询。

    大致经历两个阶段:

    • 等待数据阶段:未阻塞, 用户进程需要盲等,不停的去轮询内核。
    • 数据复制阶段:阻塞,此时进行数据复制。

    在这两个阶段中,用户进程只有在数据复制阶段被阻塞了,而等待数据阶段没有阻塞,但是用户进程需要盲等,不停地轮询内核,看数据是否准备好。

    同步非阻塞方式相比同步阻塞方式:

    优点:能够在等待任务完成的时间里干其他活了(包括提交其他任务,也就是 “后台” 可以有多个任务在同时执行)。

    缺点:任务完成的响应延迟增大了,因为每过一段时间才去轮询一次read操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。

    IO 多路复用(IO multiplexing)

    场景描述:与第二个方案差不多,餐厅安装了电子屏幕用来显示点餐的状态,这样我和女友逛街一会,回来就不用去询问服务员了,直接看电子屏幕就可以了。这样每个人的餐是否好了,都直接看电子屏幕就可以了。

    相比于阻塞IO模型,多路复用只是多了一个select/poll/epoll函数

    对于客户端来说,一般感受不到阻塞,因为请求来了,可以用放到线程池里执行;但对于执行select的操作系统而言,是阻塞的,需要阻塞地等待某个套接字变为可读

    信号驱动式IO(signal-driven IO)

    首先我们允许Socket进行信号驱动IO,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

    异步IO模型(asynchronous IO)

    场景描述:女友不想逛街,又餐厅太吵了,回家好好休息一下。于是我们叫外卖,打个电话点餐,然后我和女友可以在家好好休息一下,饭好了送货员送到家里来。这就是典型的异步,只需要打个电话说一下,然后可以做自己的事情,饭好了就送来了。

    相对于同步IO,异步IO不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。

    JAVA的IO模型

    BIO–同步阻塞的编程方式

    JDK1.4之前常用的编程方式。
    实现过程:首先在服务端启动一个ServerSocket来监听网络请求,客户端启动Socket发起网络请求,默认情况下ServerSocket会建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等待或遭到拒绝并发效率比较低

    服务器实现的模式是一个连接一个线程,若有客户端有连接请求服务端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销。当然,也可以通过线程池机制改善。

    使用场景
    BIO适用于连接数目比较小且固定的架构,对服务器资源要求高,并发局限于应用中。

    NIO–同步非阻塞的编程方式

    NIO 本身是基于事件驱动思想来完成的,当 socket 有流可读或可写入时,操作系统会相应地通知应用程序进行处理,应用再将流读取到缓冲区或写入操作系统。一个有效的请求对应一个线程,当连接没有数据时,是没有工作线程来处理的。

    服务器实现模式为一个请求一个通道,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 I/O 请求时启动一个线程进行处

    使用场景:NIO 方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程复杂,JDK1.4 开始支持。

    NIO中的几种重要角色

    有缓冲区Buffer,通道Channel,多路复用器Selector。

    Buffer

    在NIO库中,所有数据都是用缓冲区(用户空间缓冲区)处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。
    缓冲区实际上是一个数组,并提供了对数据的
    结构化访问
    以及维护读写位置等信息。

    Buffer的应用固定逻辑

    写操作顺序

    1. clear()
    2. put() -> 写操作
    3. flip() ->重置游标
    4. SocketChannel.write(buffer); ->将缓存数据发送到网络的另一端
    5. clear()

    读操作顺序

    1. clear()
    2. SocketChannel.read(buffer); ->从网络中读取数据
    3. buffer.flip()
    4. buffer.get() ->读取数据
    5. buffer.clear()

    Channel

    nio中对数据的读取和写入要通过Channel,它就像水管一样,是一个通道。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。

    Selector

    多路复用器,用于注册通道。客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理

    AIO–异步非阻塞编程方式

    进行读写操作时,只须直接调用api的read或write方法即可。一个有效请求对应一个线程,客户端的IO请求都是OS先完成了再通知服务器应用去启动线程进行处理。

    使用场景:AIO 方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用 OS 参与并发操作,编程比较复杂,JDK1.7 开始支持。

    总结

    从效率上来说,可以简单理解为阻塞IO<非阻塞IO<多路复用IO<信号驱动IO<异步IO。从同步和异步来说,只有异步IO模型是异步的,其他均为同步。

    参考https://zhuanlan.zhihu.com/p/127170201

    展开全文
  • 在jdk1.4之前JAVA只有同步阻塞IO,在jdk1.4版本更新同步非阻塞的NIO,在jdk1.7又更新了异步的NIO2.0,本文将简单介绍下Linux有哪些网络IO模型,以及JAVA中的IO所对应的网络IO模型。 理解本文之前需要先知道一个概念...

    1.概述

    在jdk1.4之前JAVA只有同步阻塞IO,在jdk1.4版本更新同步非阻塞的NIO,在jdk1.7又更新了异步的NIO2.0,本文将简单介绍下Linux有哪些网络IO模型,以及JAVA中的IO所对应的网络IO模型。
    理解本文之前需要先知道一个概念:用户空间与内核空间,即对于一次IO操作,会先将数据拷贝到系统内核缓冲区,然后从内核缓冲区拷贝到用户空间的程序缓冲区。
    recvfrom函数:此函数主要用于Linux内核从指定socket接收数据包并存储到内核缓冲区,可以用在已经建立连接的socket,也可以用在没有建立连接的socket。

    2.Linux网络IO模型

    Linu内核将所有外部设备都看做是文件操作。对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符),可以理解为fd是内核为文件创建的索引。而对socket的读写也会有相应的描述符,称为socketfd(socket 描述符),描述符就是一个数字,它指向内核中的一个结构体。Linux根据分类,提供了5种IO模型,如下:

    2.1.阻塞IO模型

    阻塞模型的IO请求过程如下:

    1. 进程调用recvfrom函数并等待数据包到达(进程阻塞等待)
    2. 数据包从内核被复制到进程的缓冲区或者发生错误返回(进程阻塞等待)

    整个过程进程都处于被阻塞状态,故被称为阻塞IO。
    默认情况下,所有的文件操作都是阻塞的。

    2.2.非阻塞IO模型

    非阻塞模型的IO请求过程如下:

    1. 进程调用recvfrom函数如果没有数据包,直接返回EWOULDBLOCK错误
    2. 轮训(1)过程
    3. 数据包从内核被复制到进程的缓冲区(进程阻塞等待)

    2.3.IO复用模型

    I/O多路复用就是通过一种机制,使一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。Linux提供了三种方式:select、poll、epoll

    2.3.1.select

    IO请求过程如下:

    1. 进程发起select调用,select遍历所有fd,监测fd状态(进程阻塞在select)
    2. fd读/写就绪时,通知进程读/写条件,进程发起recvfrom
    3. 数据包从内核被复制到进程的缓冲区(进程阻塞等待)

    select特点

    • select目前几乎在所有的平台上支持,跨平台支持比较好。
    • select是顺序扫描fd,而且单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效率的降低。
    • select机制中提供了一种fd_set的数据结构,实际上是一个long数组。select使用了三个位图来表示三个fdset的方式.

    2.3.2.poll

    poll和select的实现基本是一致,只是数据传递格式不太一样。 与select函数一样,poll也是通过顺序轮训所有fd来获取就绪的描述符,如果存在大量的非活跃状态的fd,则轮训过程也浪费了一定的开销。

    2.3.3.epoll

    epoll是在2.6内核中提出的。
    epoll特点

    • 相对于select和poll来说,epoll更加灵活,没有描述符限制。
    • epoll采用基于事件的就绪通知方式,一旦某个fd就绪,则采用callback方式通知进程。
    • epoll不用轮训所有的fd,epoll每次只遍历活跃的fd,因此在活跃的fd较少的情况下很有优势,如果大量的fd都处于活跃状态,则epoll的效率可能不如select或poll。

    2.4.信号驱动IO模型

    请求过程如下:

    1. 开启信号驱动IO功能,调用sigaction执行一个信号处理函数,并立即返回
    2. 内核收到数据包则生成一个sigio信号通知进程
    3. 进程收到sigio信号后,调用recvfrom函数
    4. 数据包从内核被复制到进程的缓冲区(进程阻塞等待)

    2.5.异步IO

    请求过程:

    1. 进程发起IO操作,通知内核并立即返回
    2. 内核收到数据包后生成一个sigio信号通知进程
    3. 内核数据包从内核被复制到进程的缓冲区并通知进程

    3.JAVA中IO模型

    JDK1.4之前使用的都是同步阻塞的BIO(阻塞IO模型)。
    JDK1.4发布的NIO特点:

    • IO模型使用的是LInux的多路复用IO模型中的epoll
    • 引入了缓冲区ByteBuffer、管道Pipe、通道Channel、文件通道FileChannel、多种字符集编解码、基于Perl实现的正则表达式类库等。

    JDK1.7对NIO进行了升级更新,称为NIO2.0,特点如下:

    • 提供了标准文件系统的SPI。
    • 能够批量获取文件属性的API。
    • 提供AIO,支持基于文件和socket的异步IO操作。
    展开全文
  • 【IO】IO模型:Linux下的五种IO模型

    千次阅读 2020-12-27 02:40:13
    Linux操作系统中,这就是一种最简单的IO模型,即阻塞IO。一般表现为进程或线程等待某个条件,如果条件不满足,则一直等下去。条件满足,则进行下一步操作。 当用户线程发出 IO 请求之后,内核会去查看数据是否就绪,...

    Linux 提供了五种 IO 模型,包括:阻塞IO、非阻塞IO、IO多路复用、信号驱动IO、异步IO。

    当用户进程请求I/O操作,发起对socket套接字的读操作时,该用户进程会执行一个系统调用,将本进程的控制权移交给内核。在unix操作系统中,一个IO操作主要经过两个阶段:

    1. 等待数据准备;等数据流到来后,会将它从网卡复制到内核空间的缓冲区(阶段一)
    2. 将数据从内核空间拷贝到用户进程中;将数据从内核缓冲区向用户进程缓冲区复制(阶段二)

    在这里插入图片描述

    PS:当进程运行在内核态时,会产生上下文切换,并且在应用程序看来,其自身用户进程此时是阻塞等待的

    1.阻塞 IO 模型

    Linux操作系统中,这就是一种最简单的IO模型,即阻塞IO。一般表现为进程或线程等待某个条件,如果条件不满足,则一直等下去。条件满足,则进行下一步操作。

    当用户线程发出 IO 请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出 CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除 block 状态。

    典型的阻塞 IO 模型的例子为:

    data = socket.read();
    

    如果数据没有就绪,就会一直阻塞在 read 方法。

    在这里插入图片描述

    recvfrom 是 Linux 系统提供给用户用于接收网络IO的系统接口,作用是从套接字上接收一个消息。

    ssize_t recvfrom(int sockfd,void *buf,size_t len,unsigned int flags, struct sockaddr *from,socket_t *fromlen);
    
    • 成功执行时,返回接收到的字节数
    • 另一端已关闭时,返回0
    • 失败返回-1,errno被设为以下的某个值
      • EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时
      • EBADF:sock不是有效的描述词
      • ECONNREFUSE:远程主机阻绝网络连接
      • EFAULT:内存空间访问出错
      • EINTR:操作被信号中断
      • EINVAL:参数无效
      • ENOMEM:内存不足
      • ENOTCONN:与面向连接关联的套接字尚未被连接上
      • ENOTSOCK:sock索引的不是套接字


    recvfrom 很关键,因为前4种IO模型都设计此系统调用。

    2.非阻塞 IO 模型

    当用户线程发起一个 read 操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个 error 时,它就知道数据还没有准备好,于是它可以再次发送 read 操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。

    所以事实上,在非阻塞 IO 模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞 IO 不会交出 CPU,而会一直占用 CPU。

    典型的非阻塞 IO 模型一般如下:

    while(true){
    	data = socket.read();   
    	if(data!= error){
    		process(data);
             break;
        }   
    }	
    

    但是对于非阻塞 IO 就有一个非常严重的问题,在 while 循环中需要不断地去询问内核数据是否就绪,这样会导致 CPU 占用率非常高,因此一般情况下很少使用 while 循环这种方式来读取数据。

    在这里插入图片描述

    3.多路复用 IO 模型

    多路复用 IO 模型是目前使用得比较多的模型。Java NIO 实际上就是多路复用 IO。

    在多路复用 IO 模型中,会有一个线程不断去轮询多个 socket 的状态,只有当 socket 真正有读写事件时,才真正调用实际的 IO 读写操作。因为在多路复用 IO 模型中,只需要使用一个线程就可以管理多个 socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有 socket 读写事件进行时,才会使用 IO 资源,所以它大大减少了资源占用。

    在 Java NIO 中,是通过 selector.select () 去查询每个通道是否有到达事件,如果没有事件,则一直阻塞在那里,因此这种方式会导致用户线程的阻塞。

    也许有朋友会说,我可以采用多线程 + 阻塞 IO 达到类似的效果,但是由于在多线程 + 阻塞 IO 中,每个 socket 对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。

    而多路复用 IO 模式,通过一个线程就可以管理多个 socket,只有当 socket 真正有读写事件发生才会占用资源来进行实际的读写操作。因此,多路复用 IO 比较适合连接数比较多的情况。

    另外多路复用 IO 为何比非阻塞 IO 模型的效率高是因为在非阻塞 IO 中,不断地询问 socket 状态时通过用户线程去进行的,而在多路复用 IO 中,轮询每个 socket 状态是内核在进行的,这个效率要比用户线程要高的多。

    不过要注意的是,多路复用 IO 模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用 IO 模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。

    在这里插入图片描述

    4.信号驱动 IO 模型

    在信号驱动 IO 模型中,当用户线程发起一个 IO 请求操作,会给对应的 socket 注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用 IO 读写操作来进行实际的 IO 请求操作。这个一般用于 UDP 中,对 TCP 套接口几乎是没用的,原因是该信号产生得过于频繁,并且该信号的出现并没有告诉我们发生了什么事情

    在这里插入图片描述

    5.异步 IO 模型

    异步 IO 模型才是最理想的 IO 模型,在异步 IO 模型中,当用户线程发起 read 操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个 asynchronous read 之后,它会立刻返回,说明 read 请求已经成功发起了,因此不会对用户线程产生任何 block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它 read 操作完成了。也就说用户线程完全不需要关心实际的整个 IO 操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接去使用数据了。

    也就说在异步 IO 模型中,IO 操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用 IO 函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用 IO 函数进行实际的读写操作;而在异步 IO 模型中,收到信号表示 IO 操作已经完成,不需要再在用户线程中调用 iO 函数进行实际的读写操作。

    注意,异步 IO 是需要操作系统的底层支持,在 Java 7 中,提供了 Asynchronous IO。简称 AIO

    在这里插入图片描述

    小结

    将这五种 IO 模型放到一起对比一下:

    前面四种 IO 模型实际上都属于同步 IO,只有最后一种是真正的异步 IO,因为无论是多路复用 IO 还是信号驱动模型,IO 操作的第 2 个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

    最后再放一个图示更清楚的参考链接

    展开全文
  • 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    万次阅读 多人点赞 2016-10-28 20:01:41
    5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO 看了一些文章,发现有很多不同的理解,可能是因为大家入切的角度、环境不一样。所以,我们先说明基本的IO操作及环境。本文是在《UNIX网络编程 卷1:套接字联网API》...

    5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

           看了一些文章,发现有很多不同的理解,可能是因为大家入切的角度、环境不一样。所以,我们先说明基本的IO操作及环境。本文是在《UNIX网络编程 卷1:套接字联网API》6.2节"I/O 模型 "的基础上,即UNIX/LINUX环境下的网络 IO环境下的理解,它里面给出的例子是读取(接收)网络UDP数据。下面简单写写自己对这些IO模型的理解。

    1、IO

           IO (Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作,通常用户进程中的一个完整IO分为两阶段:用户进程空间<-->内核空间、内核空间<-->设备空间(磁盘、网络等)IO有内存IO、网络IO和磁盘IO三种,通常我们说的IO指的是后两者。

           LINUX中进程无法直接操作I/O设备,其必须通过系统调用请求kernel来协助完成I/O动作;内核会为每个I/O设备维护一个缓冲区。

           对于一个输入操作来说,进程IO系统调用后,内核会先看缓冲区中有没有相应的缓存数据,没有的话再到设备中读取,因为设备IO一般速度较慢,需要等待;内核缓冲区有数据则直接复制到进程空间。

           所以,对于一个网络输入操作通常包括两个不同阶段:

    (1)等待网络数据到达网卡→读取到内核缓冲区,数据准备好;

    (2)从内核缓冲区复制数据到进程空间。

    2、5种IO模型

           《UNIX网络编程》说得很清楚,5种IO模型分别是阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动的IO模型、异步IO模型;前4种为同步IO操作,只有异步IO模型是异步IO操作。下面这样些图,是它里面给出的例子:接收网络UDP数据的流程在IO模型下的分析,在它的基础上再加以简单描述,以区分这些IO模型。

    2-1、阻塞IO模型

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

    1、典型应用:阻塞socket、Java BIO;

    2、特点:

    进程阻塞挂起不消耗CPU资源,及时响应每个操作

    实现难度低、开发应用较容易;

    适用并发量小的网络应用开发;

    不适用并发量大的应用:因为一个请求IO会阻塞进程,所以,得为每请求分配一个处理进程(线程)以及时响应,系统开销大。

    2-2、非阻塞IO模型

           进程发起IO系统调用后,如果内核缓冲区没有数据,需要到IO设备中读取,进程返回一个错误而不会被阻塞;进程发起IO系统调用后,如果内核缓冲区有数据,内核就会把数据返回进程。

           对于上面的阻塞IO模型来说,内核数据没准备好需要进程阻塞的时候,就返回一个错误,以使得进程不被阻塞。

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

    2、特点:

    进程轮询(重复)调用,消耗CPU的资源

    实现难度低、开发应用相对阻塞IO模式较难;

     适用并发量较小、且不需要及时响应的网络应用开发;

    2-3、IO复用模型

           多个的进程的IO可以注册到一个复用器(select)上,然后用一个进程调用该select, select会监听所有注册进来的IO;

           如果select没有监听的IO在内核缓冲区都没有可读数据,select调用进程会被阻塞;而当任一IO在内核缓冲区中有可数据时,select调用就会返回;

           而后select调用进程可以自己或通知另外的进程(注册进程)来再次发起读取IO,读取内核中准备好的数据。

           可以看到,多个进程注册IO后,只有另一个select调用进程被阻塞。

    1、典型应用:select、poll、epoll三种方案,nginx都可以选择使用这三个方案;Java NIO;

    2、特点:

    专一进程解决多个进程IO的阻塞问题,性能好Reactor模式;

    实现、开发应用难度较大;

    适用高并发服务应用开发:一个进程(线程)响应多个请求

    3、select、poll、epoll

    Linux中IO复用的实现方式主要有select、poll和epoll:

    Select:注册IO、阻塞扫描,监听的IO最大连接数不能多于FD_SIZE;

    Poll:原理和Select相似,没有数量限制,但IO数量大扫描线性性能下降;

    Epoll :事件驱动不阻塞,mmap实现内核与用户空间的消息传递,数量很大,Linux2.6后内核支持;

     2-4、信号驱动IO模型

           当进程发起一个IO操作,会向内核注册一个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用IO读取数据。

           1、特点:回调机制,实现、开发应用难度大;

    2-5、异步IO模型

           当进程发起一个IO操作,进程返回(不阻塞),但也不能返回果结;内核把整个IO处理完后,会通知进程结果。如果IO操作成功则进程直接获取到数据

    1、典型应用:JAVA7 AIO、高性能服务器应用

    2、特点:

    不阻塞,数据一步到位Proactor模式

    需要操作系统的底层支持,LINUX 2.5 版本内核首现,2.6 版本产品的内核标准特性;

    实现、开发应用难度大;

    非常适合高性能高并发应用;

    3、IO模型比较

    3-1、阻塞IO调用和非阻塞IO调用、阻塞IO模型和非阻塞IO模型

           注意这里的阻塞IO调用和非阻塞IO调用不是指阻塞IO模型和非阻塞IO模型:

                  阻塞IO调用 :在用户进程(线程)中调用执行的时候,进程会等待该IO操作,而使得其他操作无法执行。

                  非阻塞IO调用:在用户进程中调用执行的时候,无论成功与否,该IO操作会立即返回,之后进程可以进行其他操作(当然如果是读取到数据,一般就接着进行数据处理)。

           这个直接理解就好,进程(线程)IO调用会不会阻塞进程自己。所以这里两个概念是相对调用进程本身状态来讲的。

           从上面对比图片来说,阻塞IO模型是一个阻塞IO调用,而非阻塞IO模型是多个非阻塞IO调用+一个阻塞IO调用,因为多个IO检查会立即返回错误,不会阻塞进程。

           而上面也说过了,非阻塞IO模型对于阻塞IO模型来说区别就是,内核数据没准备好需要进程阻塞的时候,就返回一个错误,以使得进程不被阻塞。

    3-2、同步IO和异步IO

    同步IO:导致请求进程阻塞,直到I/O操作完成。

    异步IO:不导致请求进程阻塞。

           上面两个定义是《UNIX网络编程 卷1:套接字联网API》给出的。这不是很好理解,我们来扩展一下,先说说同步和异步,同步和异步关注的是双方的消息通信机制

                  同步:双方的动作是经过双方协调的,步调一致的。

                  异步:双方并不需要协调,都可以随意进行各自的操作。

           这里我们的双方是指,用户进程和IO设备;明确同步和异步之后,我们在上面网络输入操作例子的基础上,进行扩展定义:

                 同步IO用户进程发出IO调用,去获取IO设备数据,双方的数据要经过内核缓冲区同步,完全准备好后,再复制返回到用户进程。而复制返回到用户进程会导致请求进程阻塞,直到I/O操作完成。

                 异步IO用户进程发出IO调用,去获取IO设备数据,并不需要同步,内核直接复制到进程,整个过程不导致请求进程阻塞。

          所以, 阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动的IO模型者为同步IO模型,只有异步IO模型是异步IO。

    展开全文
  • 理解Linux五种IO模型是理解Java IO模型的基础,以钓鱼的例子为例,是否等待鱼上钩(数据准备)用来区分阻塞和非阻塞,是否手动将鱼捞出用来区分同步和异步(真正的读写操作),链接:...mid=2247484746&...
  • IO模型介绍

    千次阅读 2019-04-11 14:37:22
    IO模型 序号 类型 1 阻塞I/O 2 非阻塞I/O 3 I/O多路复用 4 信号驱动I/O 5 异步I/O I/O模型需要的基础 文件描述符   Linux 的内核将所有外部设备都看做一个文件来操作,对一个文件的读写操作...
  • 网络IO模型

    2018-10-18 16:22:23
    一、4种网络IO模型: 1、阻塞IO模型 在Linux中,默认情况下所有的socket都是阻塞的。 阻塞是指IO操作需要彻底完成后才返回到用户空间; 非阻塞是指IO操作被调用后立即返回给用户一个状态值,不需要等到IO操作彻底...
  • 面试的时候也许你被问到过IO模型,可能你知道有五种,可是却不一定能准确指出他们之间的关系,下面我们介绍下这五种IO模型五种IO模型阻塞IO非阻塞IOIO复用(select和poll)信号...
  • java IO模型详解

    万次阅读 2020-07-12 23:24:02
    IO模型介绍java IO模型BIO(Blocking IO)缺点:应用场景:NIO(Non Blocking IO)应用场景:AIO(NIO 2.0)BIO、 NIO、 AIO 对比 java IO模型 IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式...
  • 五种IO模型详解

    万次阅读 多人点赞 2018-03-20 11:26:52
    在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。下面就分别来介绍一下这5种IO模型的异同。1.阻塞IO模型 最传统的一种IO模型,即在读写数据过程中会发生...
  • IO模型解析

    千次阅读 2016-04-26 15:15:01
    IO模型解析标签 : IO1.1 IO模型概述在服务器端网络编程我们经常会用到一些IO模型,有如下几种IO模型 同步阻塞IO 同步非阻塞IO IO多路复用 异步IO 信号驱动IO 1.2 IO模型涉及的基本概念。要想好好理解上面的IO模型,...
  • IO模型浅析

    2015-10-15 16:00:54
    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: 同步阻塞IO(Blocking IO):即传统的IO模型。 同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为...
  • 常见IO模型详解

    2019-02-14 16:18:27
    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: 同步阻塞IO(Blocking IO):即传统的IO模型。 同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为...
  • java io模型

    2021-06-13 16:06:52
    请问下csdn有好一些的关于java io模型文章吗?大部分文章看的我云里雾里
  • 浅析IO模型

    2020-05-27 21:41:13
    目录概念IO模型同步阻塞IO同步非阻塞IO多路复用IO信号驱动IO异步非阻塞IO 概念 谈论模型之前,先了解一下相关的概念知识,扩展一下深度。 IO如何交互呢? 对于一个应用程序即一个操作系统进程来说,它既有内核空间...
  • 一文读懂IO模型和Reactor线程模型

    千次阅读 2019-09-21 15:52:12
    Reactor线程模型,Linux IO模型
  • 4种网络IO模型

    2019-06-28 09:14:21
    4种网络IO模型 当一个网络*IO*发生时,它会涉及到...为了解决网络IO问题,有四种网络IO模型:(1)阻塞IO模型(2)非阻塞IO模型(3)多路复用IO模型(4)异步IO模型 阻塞IO模型 在Linux中,默认情况下所有的socket都是阻塞的...
  • 浅析IO,NIO和五种IO模型 文章目录浅析IO,NIO和五种IO模型一:几个基本的概念二:同步,异步,阻塞,非阻塞1.同步:2.异步:3.阻塞:4.非阻塞:注意:三:阻塞IO,非阻塞IO,同步IO,异步IO1.阻塞IO:2.非阻塞式IO:4....
  • 五种IO模型

    2021-01-22 15:42:36
    在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。 1、阻塞IO模型 最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。 当用户线程发出IO请求之后,...
  • 高性能IO模型浅析

    万次阅读 2017-11-10 11:56:03
    高性能IO模型浅析   服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型。 (2)同步非阻塞IO(Non-blocking IO):默认创建的...
  • 网络编程二-LINUX网络IO模型

    万次阅读 2019-08-10 10:24:46
    非阻塞IO模型 IO复用模型 信号驱动IO 异步IO模型 5个I/O模型的比较 今天台风利奇马就要登陆浙江了,风那叫一个大啊,所以,就别出门了,老老实实在家学习看博客吧哈O(∩_∩)O 前言:网络编程里通用常识 既然...
  • 目录IO模型阻塞与非阻塞同步与异步阻塞IO非阻塞IO信号驱动IO多路复用IO异步IO IO模型 根据各自的特性不同,IO模型被分为阻塞IO、非阻塞IO、信号驱动IO、异步IO、多路复用IO五类。 最主要的两个区别就是阻塞与非阻塞...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 318,579
精华内容 127,431
关键字:

io模型