四种 IO 模型:
 
    首先需要明确,IO发生在 用户进程 与 操作系统 之间。可以是客户端IO也可以是服务器端IO。
  • 阻塞IO(blocking IO):
    在linux中,默认情况下所有socket都是blocking:kernel和用户都在阻塞等待数据。

 
  • 非阻塞IO(non-blocking):
       用户程序重复调用系统调用 recvfrom ,等待 return OK信号。 polling轮询

        为什么没有Block:用户进程发出read请求后 ,如果kernel中的数据还没有准备好,那么就会立即返回来一个error信号。对于用户角度来讲他并没有等待,而是立即就得到了一个结果。接下来,用户进程就会不断主动询问kernel有没有准备好。
 
 
  • IO多路复用(IO multiplexing)
    常用的方法就是 select 和 epoll 。这种方法也和叫作 事件驱动IO
这种方式的好处在于:kernel的单个process可以同时处理多个网络连接IO。将轮询的工作统一交给kernel内核监管的函数select/epoll(该函数由用户态 调用,kernel监管)函数。用户可以将多个socket注册到同一个select中,kernel来监管select中注册的IO,一旦发任何一个socket现数据准备好了,就将通知用户process,调用read将数据从kernel拷贝到用户进程。这样用户process就从轮询中解放出来,只需要静静地等待select函数返回即可。当然,这个过程中,用户也是block的,虽然是block的(被select block) 但是什么都不做的block和不断去 “轮询”的block,还是不同的!这样可以减少用户process的负担。
 
这里就要插入另外一个内容:select、poll、epoll
 
select主要的缺陷有三个:
1)最大并法数限制:受限于一个进程能够打开的FD(文件描述符)的个数。在linux/posix_types.h头文件有这样的声明:#define __FD_SETSIZE    1024  表示select最多同时监听1024个,因此最大并发数就被限制了。
2)效率问题:select每次都会线性扫描【类似数组来存储】全部的FD集合,这样效率就会呈线形下降。
3)内核/用户空间内存拷贝。
 
poll 基本等于select 后两点都没有改善
 
epoll 
  1. int epoll_create(int size);
  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  3. int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
 
对比select 就有如下优点:
1)   最大并发数不受限制。上限是:当前系统中打开文件的最大数目。
2)效率高。因为epoll只管当前活跃的socket,epoll维护一颗红黑树。那些注册了的socket或者说是文件描述符,就会高效的在树上插入或者删除。
        epoll的高效就在于(引用):“epoll_ctl往里塞入百万个句柄时,epoll_wait仍然可以飞快的返回,并有效的将发生事件的句柄给我们用户。这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。
        而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已,如何能不高效?!
        那么准备就绪的列表list是怎么维护的呢?当我们执行epoll_ctl的时候,除了把socket放到epoll文件系统里file对应的红黑树上之外,还会在内核的中断处理程序上注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪的list中,也就是当socket有数据到达后,内核会把网卡上的数据copy到内核中后就把socket插入到准备列表list中。”
        最后,总结一下:
1 当用户调用epoll_create后,内核会在内存cache中创建一个红黑树就绪列表
2 当用户调用epoll_ctl注册 socket(文件句柄)时,内核会在红黑树上查找是否有该句柄。如果存在,则立即返回。如果没有,那么在红黑树的节点上增加,然后在内核注册回调函数,用于当中断来临的时候,向中断就绪链表中插入数据。
3 当用户调用epoll_wait时,立即返回就绪列表中的数据。
 
关于epoll的LT(水平触发)和ET(边缘触发)两种工作模式:
LT:只要改句柄上的事件没有处理完,那就此此返回。
ET:只返回一次。
实现的原理在于对list就绪列表的清空机制上。清空后,如果是LT且未处理完,就再放回到就绪列表中。
 
 
 
 
 
  • 异步IO(Asynchronous IO)

    用户发起read之后,服务器端kernel会立刻返回。用户process就会去做其他事情去了。这种情况下,对于服务器来说,接收到每一个IO请求都需要开辟一个线程去专门去处理。
3)用户与内核共享内存,no more 内存拷贝。
 
######################################################################################
最后说一说,
 
1)阻塞Block与非阻塞Nonblock的区别:
        Block会让用户进程Block住直到请求的IO操作完成;NonBlock会在kernel正在准备数据的时候,立即返回一个结果,知道这个结果是OK就绪信号,那么接下来进程读取数据,done;
 
2)同步synchronous与异步asynchronous的区别:
首先定义:
A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
An asynchronous I/O operation does not cause the requesting process to be blocked; 
        上面所讲的block IO 、Non—block IO、IO 多路复用都属于 同步IO。Non-block 与其他方式一样,这里所说的block是当发生IO operation的时候,也就是调用 recv_from系统调用时,会发生block,以完成数据从内核态copy到用户态的过程。以上三种方式都是会block的。而asynchronous IO则不一样,当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。

各个IO Model的比较如图所示:

 
 

最后,再举几个不是很恰当的例子来说明这四个IO Model:
有A,B,C,D四个人在钓鱼:
A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆;
B的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆;
C用的鱼竿和B差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来;
D是个有钱人,干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给D发个短信。

参考:http://blog.csdn.net/fuyuehua22/article/details/38304495

    

四种IO模型的更多相关文章

  1. 图解四种 IO 模型

    最近越来越认为,在讲解技术相关问题时,大白话固然很重要,通俗易懂,让人有想读下去的欲望.但几乎所有的事,都有两面性,在看到其带来好处时,不妨想想是否也引入了不好的地方. 例如在博客中,过于大白话的语言 ...

  2. Linux五种IO模型(同步 阻塞概念)

    Linux五种IO模型 同步和异步 这两个概念与消息的通知机制有关. 同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.比如,调用readfrom系统调用时,必须等待IO操 ...

  3. 漫谈五种IO模型

    阅读目录 1 基础知识回顾 2 I/O模式 3 事件驱动编程模型 网络编程里常听到阻塞IO.非阻塞IO.同步IO.异步IO等概念,搞清楚这些概念之前,还得先回顾一些基础的概念. 1 基础知识回顾 注意 ...

  4. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  5. Linux 网络编程的5种IO模型:异步IO模型

    Linux 网络编程的5种IO模型:异步IO模型 资料已经整理好,但是还有未竟之业:复习多路复用epoll 阅读例程, 异步IO 函数实现 背景 上一讲< Linux 网络编程的5种IO模型:信 ...

  6. 正确理解这四个重要且容易混乱的知识点:异步,同步,阻塞,非阻塞,5种IO模型

    本文讨论的背景是Linux环境下的network IO,同步IO和异步IO,阻塞IO和非阻塞IO分别是什么 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进 ...

  7. (四)五种IO模型

    基本概念 我们之前编写的套接字程序都是阻塞式的,其实这也是默认的形式.现在我们需要明确一些概念: 用户空间和内核空间 首先要明确,用户启动的应用程序在系统中以一个进程的形式存在,而无论对于网络数据还是 ...

  8. Atitit  五种IO模型attilax总结 blocking和non-blocking synchronous IO和asynchronous I

    Atitit  五种IO模型attilax总结 blocking和non-blocking synchronous IO和asynchronous I   1.1. .3 进程的阻塞1 1.2. 网络 ...

  9. 聊聊 Linux 中的五种 IO 模型

    本文转载自: http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666538919&idx=1&sn=6013c451 ...

随机推荐

  1. Android定位(是否使用GPS进行定位)

    TencentLocationRequest request = TencentLocationRequest.create(); request.setRequestLevel(TencentLoc ...

  2. Java并发包——线程池

    Java并发包——线程池 摘要:本文主要学习了Java并发包中的线程池. 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520/p/3932921.html ...

  3. 几点平时不太注意的CSS知识

    1:文本显示的时候,我们发现左右参差不齐,text-align:justify  就能让文本左右都齐刷刷的啦: 2:input标签的内容,处于安全考虑,有时候我们并不希望别人黏贴复制,这时候这样干:& ...

  4. swift学习笔记(四)关于类的继承

    在swift中,继承是区分类与其它对象的基本特征 继承后的子类能够重写父类的方法,包含类方法和实例方法,属性和附属脚本(subscript) 在继承过程中,构造器方法init()是不被继承的,须要显示 ...

  5. AutoCAD菜单加载失败 找不到文件mnc 怎么办

    菜单加载失败,找不到文件 SWFILECONV(mnu/mns/mnc)   找到CAD安装目录下的swfileconv.arx文件,用记事本打开,清空内容,然后保存即可.  

  6. css的white-space属性导致了空格问题——查看十六进制发现2020变成了c2a0

    今天发现了一个奇怪的问题.从文本编辑器(notepad++)中把一段文本输入到easyui的textbox文本框(textarea)中,不进行不论什么的操作.直接再从文本框中把文本拷贝出来贴到文本编译 ...

  7. JSON介绍及Android最全面解析方法(Gson、AS自带org.son、Jackson解析)

    前言 今天,我们来介绍一下现今主流的数据交换格式-JSON! 相同作为主流为数据交换格式-XML,假设有兴趣能够阅读我写的XML及其DOM.SAX.PULL解析方法和对照 文件夹 定义 JavaScr ...

  8. document.getElementsByClassName("head")[0].parentElement

    document.getElementsByClassName("head")[0].parentElement

  9. 爬虫定时任务 redis 减轻 mysql 读的压力 加层

    非工作时间,定时任务爬虫大量mysq短链接,影响了其他业务的,mysql 报 too many connections  错误 将爬虫url池放入到redis中,单独的脚本维护redis url池的更 ...

  10. spring 的核心接口

    spring有两个核心接口,BeanFactory 和ApplicationContext  ,其中ApplicationContext 是BeanFactory的子接口.他们代表了Spring容器. ...