同步阻塞式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. thinkpad x260在ubuntu 14.04lts wifi驱动安装 ( ubuntu iwlwifi驱动 都可行 )

    实验室要新购笔记本x260,用于ROS调试,装上ubuntu-ros后,发现wifi不支持. 查阅大量资料,如下: http://www.ubuntu.com/certification/hardwa ...

  2. Asp.net中JQuery、ajax调用后台方法总结

    通过上一篇文章实例的实现,整个过程当中学习到很多知识点,了解了Jquery.Ajax在asp.net中的运用,加以总结,其实原理都是一样的,理解了一种,其他的注意很少的区别就可以了.灵活运用: 1.有 ...

  3. Get Form type using javascript in CRM 2011

    Get from type var type = Xrm.Page.ui.getFormType(); getFromType() function returns integer value for ...

  4. iOS开发支付集成之微信支付

    这一篇是<iOS开发之支付>这一部分的继支付宝支付集成,银联支付集成第三篇,微信支付.在集成的时候建议都要去下载最新版的SDK,因为我知道的前不久支付宝,银联都更新了一次,微信的不太清楚更 ...

  5. PR 审批界面增加显示项方法

    PR 审批界面增加显示项 解决方法 Step 1:       进入审批界面: Step 2:       在上图中,点击左下角'About this Page'查看数据源 点击上图中'Expand ...

  6. Java进阶(十)java tomcat中context配置

    Tomcat中Context的配置 问题: java tomcat中<context> docBase属性是什么意思? 元素的属性: path:指定访问该Web应用的URL入口.  doc ...

  7. JNI设置C++与java的结合(2)

    我们可以看到其中有四个函数声明, Java_完整类名_方法名, 完整类名包括了包名, 例如demo.Sample1是完整类名, 对应的这里就是demo_Sample1. 在注释中我们可以看到这样一个东 ...

  8. 【Android 应用开发】GitHub 优秀的 Android 开源项目

    原文地址为http://www.trinea.cn/android/android-open-source-projects-view/,作者Trinea 主要介绍那些不错个性化的View,包括Lis ...

  9. win32 线程通信初步

    // 线程通信机制.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #define NUM_THREADS 10 #include < ...

  10. OPEN A PO ORDER OR SO ORDER

    OPEN PO ORDER fnd_function.Execute(Function_Name => 'PO_POXPOEPO', Open_Flag => 'Y', Session_F ...