同步阻塞式IO开发简单,但在处理IO密集的并发任务时,非常浪费CPU资源,性能低;并且,当一个进程(线程)含有多个套接字上时,同步阻塞式IO会带来问题:因为同步阻塞式IO只支持进程(线程)阻塞在一个套接字上,其余套接字上的事件将得不到及时处理。

为解决这些问题,IO编程的世界诞生了更多的IO模型及实现,这些实现不仅可以用在网络编程中,同样可以用在本地IO编程中。

在此先做说明,阻塞与非阻塞、同步与异步是两组不同的概念。

1.1         IO复用

IO 复用技术是指,调用IO 复用的api(select、pselect、poll、epoll等)时,其阻塞在多个文件描述符(套接字)上,这与普通的阻塞式IO函数如:read、write、close等不同,这些函数都是阻塞在一个文件描述符上。以select为例,select等待多个文件描述符(套接字)上发生IO事件,可以设置等待超时,select只返回描述符就绪的个数(一般可认为是IO事件的个数),用户需要遍扫描整个描述符集处理IO时间。伪代码如下:

while(true){

select(描述符集,超时值)

for(fd in 描述符集合){

if ( fd has IO事件){

处理IO事件

}

}

}

真实的select要比此复杂,其可指定自己关心的描述符集,分读、写、出错三种描述符集。

Select的缺点很明显,当描述符集很大时,遍历一遍集合的耗时将会很大,因此会有一个FD_SETSIZE宏限制。后续的epoll则优化的此问题,只返回发生的IO事件及其关联的描述符。

1.2         非阻塞IO(NIO)

非阻塞式IO与阻塞式IO不同的是,非阻塞式IO发现IO暂不可进行时,不阻塞,而是直接返回错误。可结合轮询构成一种可用的模型,但很少见。伪代码如下:

while(true) {

ret=recv(描述符)

if(ret != 错误 && ret != 结束){

处理IO事件

}

}

1.3         信号(事件)驱动IO

信号驱动式IO在IO事件就绪后,向用户程序发送信号或者直接执行回调(调用用户进程空间中的函数),用户在回调函数中执行IO处理。纵观各种读写的IO操作,都是首先等待内核准备好数据或准备好存放数据的内核空间,然后执行内核空间与用户进程空间之间的数据拷贝。其中,信号驱动式IO模型就是在内存做好准备之后,向用户进程发送信号,通知用户进程执行剩下的数据拷贝的操作。以读事件为例,过程如图:

可以看到,信号驱动模式中,读取数据时,依然使用的是同步IO。因此epoll可以说是一种同步非阻塞的支持IO多路复用的IO模型,但是在linux kernel 2.6版本之后,epoll使用了mmap(文件内存映射系统调用),使得数据从内核拷贝到用户进程空间的过程被省略了,于是它有了下面要讲的异步IO的特点,由此进一步产生了epoll到底是异步非阻塞还是同步非阻塞IO模型的一些争议。

1.4         异步IO(AIO)

异步IO与信号驱动IO模型,仅在于1、通知发生在数据从内核空间读取到用户空间(读)或者数据从用户空间写入到内核空间之后(写)。2、使用的是异步的系统调用api接口。以读为例,过程如图:

可以看到异步IO实在内核已完成IO操作之后,才发起通知,时机不同于信号(事件)驱动式IO。Linux中异步IO系统调用皆以aio_*开头。操作完成之后的通知方式可以是信号,也可以是用户进程空间中的回调函数,皆可通过aiocb结构体设置。目前linux 虽然已有aio函数,但是即使是epoll也并没有直接使用aio,而是通过非阻塞+mmap达到了伪AIO的效果,这与windows iocp和FreeBSD的kqueue纯异步的方案是不同的,普遍的测试结果,epoll性能比iocp还是有微小的差距。

高性能网络IO模型的更多相关文章

  1. IO模型及高性能网络架构分析

    前言 操作系统一次IO调用过程 应用程序发起的一次IO操作包含两个阶段: IO调用:应用程序进程向操作系统内核发起调用. IO执行:操作系统内核完成IO操作. 操作系统内核完成IO操作还包括两个过程: ...

  2. 框架篇:见识一下linux高性能网络IO+Reactor模型

    前言 网络I/O,可以理解为网络上的数据流.通常我们会基于socket与远端建立一条TCP或者UDP通道,然后进行读写.单个socket时,使用一个线程即可高效处理:然而如果是10K个socket连接 ...

  3. 服务器端网络编程之 IO 模型

    引言  从 T 跳槽到 A 之后,我的编程语言也从 C++ 转为 了 Java.在 T 做的偏服务器端开发,而在 A 更偏向于业务开发.上周在 A 公司组内做了一个<服务器端高性能网络编程> ...

  4. Netty学习之IO模型

    目录 1.1 同步.异步.阻塞.非阻塞     同步 VS 异步         同步         异步     阻塞 VS 非阻塞         阻塞         非阻塞     举例   ...

  5. 聊聊Netty那些事儿之从内核角度看IO模型

    从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...

  6. 高性能IO模型浅析

    高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking  ...

  7. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  8. Linux下常见的IO模型

    前言 阻塞IO(blocking IO) 非阻塞IO(nonblocking IO) IO复用(IO multiplexing) 异步IO(asynchronous IO (the POSIX aio ...

  9. IO模型

    前言 说到IO模型,都会牵扯到同步.异步.阻塞.非阻塞这几个词.从词的表面上看,很多人都觉得很容易理解.但是细细一想,却总会发现有点摸不着头脑.自己也曾被这几个词弄的迷迷糊糊的,每次看相关资料弄明白了 ...

随机推荐

  1. 【Unity Shaders】Reflecting Your World(反射吧!)介绍

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  2. 【Django】优化小技巧之清除过期session

    事情是这样的,大概也就几万注册用户的站点(使用django1.6), session 存储在关系型数据库,这次上线之后发现session表几十万数据了,过期session没有被自动删除 思考 官网 s ...

  3. NDK工具开发Jni,Android studio jni开发

    NDK工具开发JNI 对于JNI的作用,我这边就不详细说明了,百度google 有很多这样的介绍,这边着重详解AS使用NDK工具开发,调C的流程. 1,创建工程 2,创建native方法 //该类的路 ...

  4. R12 - Error 'Unable to process your transaction. The operating unit is either invalid or it cannot b

    In this Document   Symptoms   Cause   Solution   Still Have Questions?   References APPLIES TO: Orac ...

  5. Leetcode_36_Valid Sudoku

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42528601 Determine if a Sudoku ...

  6. Android群英传帝落篇——程序人生,路漫漫其修远兮,吾将上下而求索!

    Android群英传帝落篇--程序人生,路漫漫其修远兮,吾将上下而求索! 当写这篇博客的时候,自2016-02-22到现在5.2号,一晃眼,也㓟两个多月就过去了,我才将这本书看完,虽然写笔记花了很大的 ...

  7. WINCE的批处理

    WINCE上没有提供象window一样的bat文件,如果需要类似功能可以借助第三方程序MortScript MortScript是一个运行于WINCE上的免费脚本解释程序,脚本文件为.mscr或.mo ...

  8. Bookmarkable Pages

      Build a Bookmarkable Edit Page with JDeveloper 11g Purpose In this tutorial, you use Oracle JDevel ...

  9. SpriteBuilder中关于大量CCB文件的数字命名建议

    开发者总是频繁的填充文件名字使用额外的0,以此来对抗长久以来的长痘:数字排序.如果你觉得在数字名字前添加额外的0是一个好主意,比如说Level0001,因为可能你会创建数以千记的关卡--请不要这样做! ...

  10. 【50】java 匿名内部类剖析

    匿名内部类介绍: 匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 匿名内部类的声明 ...