IO模型解析

IO模型解析

标签 : IO


1.1 IO模型概述

在服务器端网络编程我们经常会用到一些IO模型,有如下几种IO模型

  1. 同步阻塞IO
  2. 同步非阻塞IO
  3. IO多路复用
  4. 异步IO
  5. 信号驱动IO

1.2 IO模型涉及的基本概念。

要想好好理解上面的IO模型,我们首先来明确如下几个概念。

1. 同步:当程序发生一次功能调用的时候,需要等待这次调用返回然后才能进行下一步操作。也就是事情要一件一件做。

eg:单线程程序中的顺序执行。

2. 异步:当程序发生一次调用的时候,无需等待这次调用的返回,就可以继续执行程序。这次调用完成后会通过状态、通知、回调来通知调用者。

eg:ajax调用服务器。

同步异步的主要区别就是:数据拷贝的时候“进程”是否阻塞。

  1. 阻塞:当调用返回之前,程序的处在挂起的状态(CPU不会给分配时间片),调用返回后才会从挂起状态转换成运行状态。
  2. 非阻塞:发生调用后,调用函数不会阻塞这个线程。而是立刻返回。

阻塞和非阻塞的主要区别就是:应用程序的调用是否能立即返回。

在明确这些概念之后我们开始

2.1 同步阻塞IO

  应用进程在发起recvfrom调用的时候。会一直阻塞。等到调用完成(完成数据的准备和数据的拷贝)。

2.2 同步非阻塞IO

  recvfrom轮询发起调用,但是每次调用立即返回。所以是非阻塞。recvfrom进程依旧要等待数据拷贝完成后才能继续执行,所以是同步。加起来就是同步非阻塞。但是像这种不断轮询也会消耗CPU的资源。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。

  

2.3 IO多路复用

  IO多路复用模式是建立在内核提供的select、poll函数的基础上,提供一种可以在同一线程内处理多个I请求的效果。

  观察图中的流程我们也会发现select函数同样会阻塞,看起赖好像比阻塞模式并没有什么优势。但是这两个函数可以阻塞多个IO操作。直到数据准备完成,用户线程开始发起请求去读取准备好的数据。

  用户可以注册多个socket然后不断的调用select来获取被激活的socket。这样就完成了一个线程处理多个IO请求的目的。伪代码如下。

{
    //socket添加到select监视中
    select(socket);
    while(true) {
        //阻塞方法 获取激活的socket
        sockets = select();
        for(socket : sockets) {
            if(can_read(socket)) {
                //读取数据
                read(socket, buffer);
                //处理逻辑
                process(buffer);
            }
        }
    }
}

linux还提供了一个epoll系统调用,epoll是基于事件驱动方式,而不是顺序扫描,当有fd就绪时,立即回调函数rollback;

  虽然在上面讲述的方式中可以在一个线程内同时处理多个IO请求,但是IO请求的过程还是阻塞在Select函数上的,平均时间甚至比同步阻塞IO的时间还要长。如果IO请求不阻塞在select上,用户可以注册自己的socket或者IO请求,然后继续做自己的事情(不阻塞)。等到数据准备完成再进行处理。这样就可以提高CPU利用率。

  IO多路复用模型使用Reactor设计模式实现了这个机制。

  • EventHandler 抽象类表示IO时间的处理器。get_handle可以获取文件引用,handle_event可以完成对文件的操作,继承自EventHandler的子类可以定制不同的处理方式。
  • Reactor 用于管理EventHandler(注册,删除等)。handle_events实现事件循环,不断调用同步事件多路分离器(一般是内核)的多路分离函数select,只要某个文件被激活(可读/写等),select就返回(阻塞),handle_events就会调用与文件句柄关联的事件处理器的handle_event进行相关操作。

如上图所示, 用户线程会向Reactor注册IO时间,Reactor的handle_events事件会循环处理(不断的调用多路分离函数)此时用户线程可以继续执行其他操作。当Reactor发现有被激活的socket的时候会通知用户线程(或者调用回调函数)执行handle_event进行数据的读取处理等工作。

  用户线程使用IO多路复用模型的伪代码描述为

// class UserEventHandler
    void handle_event() {
        if(can_read(socket)) {
            read(socket, buffer);
            process(buffer);
        }
    }
{
    Reactor.register(new UserEventHandler(socket));
}

用户需要重写EventHandler的handle_event函数进行读取数据、处理数据的工作,用户线程只需要将自己的EventHandler注册到Reactor即可。

Reactor中handle_events事件循环的伪代码大致如下。

// class Reactor
    handle_events() {
        while(1) {
            sockets = select();
            for(socket in sockets) {
                get_event_handler(socket).handle_event();
            }
        }
}

事件循环不断地调用select获取被激活的socket,然后根据获取socket对应的EventHandler,执行器handle_event函数即可。

2.4 异步IO

告知内核启动某个操作,并让内核在整个操作完成后(包括将数据从内核拷贝到用户自己的缓冲区)通知我们。

参考文章

http://www.cnblogs.com/fanzhidongyzby/p/4098546.html

http://blog.csdn.net/jay900323/article/details/18141217

http://www.2cto.com/os/201408/326734.html

http://blog.csdn.net/colzer/article/details/8169075

时间: 2024-08-30 11:17:18

IO模型解析的相关文章

Http协议和IO模型

HTTP 协议和IO模型 一:HTTP协议 http协议:HyperText Transfer Procotol超文本传输协议,http协议是无状态的,监听在80端口,TCP协议上.HTTP协议的特点有以下几点: 1.支持客户/服务器模式.2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有GET.HEAD.POST.每种方法规定了客户与服务器联系的类型不同.由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快.3.灵活:HTTP允许传输任意类型的数据

TCP下IO模型优劣比较

多线程模型适用于处理短连接,且连接的打开关闭非常频繁的情形,但不适合处理长连接.多线程模型默认情况下,(在Linux)每个线程会开8M的栈空间,再TCP长连接的情况下,2000/分钟的请求,几乎可以假定有上万甚至十几万的并发连接,假定有10000个连接,开这么多个线程需要10000*8M=80G的内存空间!即使调整每个线程的栈空间,也很难满足更多的需求.甚至攻击者可以利用这一点发动DDoS,只要一个连接连上服务器什么也不做,就能吃掉服务器几M的内存,这不同于多进程模型,线程间内存无法共享,因为所

Java IO模型&NIO

Java IO模型&NIO Java IO模型NIO 楔子 概述 网络服务 经典的服务设计 经典的SocketServer循环阻塞 可伸缩目标 分而治之 事件驱动设计 背景知识AWT 事件 Reactor 模式 Reactor基础模式 Java NIO 支持 Channels Buffers Selectors SelectionKeys Reactor 模式实践 第一步初始化 第二步循环分发 第三步接收者 第四步 Handler设置 第五步请求处理 还有一种状态Handler 多线程版本Rea

python全栈开发基础【第二十七篇】IO模型

相关名词解析 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实绝大多数函数都是同步调用.但是一般而言,我们在说同步.异步的时候, 特指那些需要其他部件协作或者需要一定时间完成的任务. #举例: #1. multiprocessing.Pool下的apply #发起同步调用后,就在原地等着任务结束, 根本不考虑任务是在计算还是在io阻塞,总之就是一

通过实例理解Java网络IO模型

网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的.以下是一个典型的应用服务器上的连接情况.客户的各种设备通过Http协议与Tomcat进程交互,Tomcat需要访问Redis服务器,它与Redis服务器也建了好几个连接.虽然客户端与Tomcat建的是短连接,很快就会断开,Tomcat与Redis是长连接,但是它们本质上都是一样的.建立一个Socket后

Day30:IO模型

一.IO模型 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wiki,就认为asynchronous IO和non-blocking IO是一个东西.这其实是因为不同的人的知识背景不同,并且在讨论这个问题的时候上下文(context)也不相同.所以,为了更好的回答这个问题,先限定一下本文的上下文.本文讨论的背景是Linux

走入计算机的第三十九天(python终结篇之IO模型)

一.IO模型 1.IO模型分类 1.阻塞IO--------blocking IO 2.非阻塞IO------nonblocking IO 3. 多路复用IO------- multiplexing 4.信号驱动IO-------signal driven IO (工作中不会使用到,只是作为了解) 5.异步IO------- asynchronous IO 2.通常情况下IO默认操作分为两个阶段(默认都是阻塞IO) 1.准备等待数据阶段,相当于请求操作系统是否有数据发送过来(调用IO操作). 2

IO模型介绍 以及同步异步阻塞非阻塞的区别

阻塞:用户进程访问数据时,如果未完成IO,等待IO操作完成或者进行系统调用来判断IO是否完成非阻塞:用户进程访问数据时,会马上返回一个状态值,无论是否完成 同步:用户进程发起IO(就绪判断)后,轮询内核状态异步:用户进程发起IO后,可以做其他事情,等待内核通知 介绍一下IO模型 网络IO模型和文件IO模型是一样的,上图是IO的5种模型,包括阻塞IO.非阻塞IO.多路复用IO.信号驱动的IO.异步IO. 一次IO包括两个过程,内核数据准备 .把数据从内核空间copy到用户空间. 1.阻塞IO(re

Linux IO模型与Java NIO

概述看Java NIO一篇文章的时候又看到了"异步非阻塞"这个概念,一直处于似懂非懂的状态,想解释下到底什么是异步 什么是非阻塞,感觉抓不住重点.决定仔细研究一下.本文试图研究以下问题: web server原理,bio的connector与nio的connector在架构上到底什么区别? NIO的优势到底在哪里,是如何应用到实践中的? 同步/异步.阻塞/非阻塞到底是什么概念,引出的IO模型同步阻塞.同步非阻塞.异步阻塞.异步非阻塞的具体使用场景,适用的场景是怎样的? bio nio也