`
csd_ali
  • 浏览: 136065 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

深入浅出异步I/O模型

阅读更多

      从上篇文章的介绍我们知道linux内核根据TCP/IP网络模型,给我们隐藏了传输层以下的网络传输细节,我们的网络应用程序只需要针对socket编程即可。这篇我们立足网络数据包的I/O。谈谈linux的一些I/O知识,以及Java的NIO.

 1.  基础知识

      我们知道Linux的内核将所有外部设备都可以看做一个文件来操作。那么我们对与外部设备的操作都可以看做对文件进行操作。我们对一个文件的读写,都通过调用内核提供的系统调用;内核给我们返回一个file descriptor(简称:fd,文件描述符);我们通过 ls -l  /proc/${pid}/fd/ 可以看到进程${pid}占用的所有描述符,或者lsof -p ${pid}; 而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符);描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性) ; 那么我们的应用程序对文件的读写就通过对描述符的读写完成。

     系统调用是如何完成一个I/O操作的呢? linux将内存分为内核区,用户区; linux内核给我们管理所有的硬件资源,应用程序通过调用系统调用和内核交互,达到使用硬件资源的目的; 应用程序通过系统调用read发起一个读操作;这时候内核创建一个文件描述符,并通过驱动程序向硬件发送读指令,并将读的的数据放在这个描述符对应结构体的缓存区。但这个结构体是在内核内存区的。需要将这个数据读到用户区。这样完成了一次读操作;

     但是大家都知道I/O设备相比cpu的速度是极慢的。linux提供的read系统调用,也是一个阻塞函数。这样我们的应用进程在发起read系统调用时,就必须阻塞,就进程被挂起而等待文件描述符的读就绪;

      这里,我们先了解一下,什么是文件描述符读就绪,什么是写就绪?

       读就绪:就是这个文件描述符的接收缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的当前大小;

       写就绪:该描述符发送缓冲区的可用空间字节数大于等于描述符发送缓冲区低水位标记的当前大小。(如果是socket fd,说明上一个数据已经发送完成)。

       接收低水位标记和发送低水位标记:由应用程序指定,比如应用程序指定接收低水位为64个字节。那么接收缓冲区有64个字节,才算fd读就绪;

2.各种I/O模型比较

    有没有办法能让我们在I/O时,不让我们的应用程序阻塞;从上边的分析我们知道向内核发起一个I/O操作,要经过等待fd就绪+内核数据到用户数据区复制,完成一次I/O;

    Linux POSIX是这样定义同步I/O 和 异步I/O的:

  •    同步I/O操作(synchronous I/O operation):导致请求进程阻塞,直到I/O操作完成。
  •    异步I/O操作(asynchronous I/O operation): 不导致请求进程阻塞。

     根据上述定义,我们的前四种模型------阻塞式I/O模型,非阻塞式I/O模型、I/O多路复用模型和信号驱动式I/O模型,因为其中真正的I/O操作将阻塞进程。只有异步I/O模型与POSIX定义的异步I/O相匹配;

 

 

                                  图: Linux 提供的所有I/O模型

    阻塞式:最普通的I/O模型;原生的read/write系统调用,默认是阻塞模式;导致进程阻塞;

    非阻塞:这种方式通过指定系统调用read/write的参数为非阻塞,告知内核fd没就绪时,不阻塞进程,而是返回一个错误码,应用进程死循环轮询,直到fd就绪;

    异步非阻塞(I/O复用):linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select;这样select/poll可以帮我们侦测许多fd是否就绪;但是select/poll是顺序扫描fd是否就绪,而且支持的fd数量有限。linux还提供了一个epoll系统调用,epoll是基于事件驱动方式,而不是顺序扫描,当有fd就绪时,立即回调函数rollback;

    异步非阻塞(信号驱动式I/O):内核在描述符就绪时发送SIGIO信号通知进程,进程通过信号处理函数接收数据;

    异步I/O(AIO):  告知内核某个操作,并让内核在整个操作(包括将数据复制到我们的进程缓冲区)完成后通知我们。这种模型和信号驱动式I/O模型区别在于:信号驱动式I/O由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是内核通知我们I/O操作何时完成。(此模型linux 2.6 内核推出)

 

3. java的NIO(new i/o)

    我们知道jdk 1.4版本里推出了java nio .此后java的很多网络应用都重写了底层I/O模块,大大提高并发性能;包括tomcat, jetty等;

     java nio api 里通过将许多fd扔给一个Selector去检测fd是否就绪;

     那么java 的nio使用的是那种I/O模型呢?

     通过查看jvm代码:(下载地址:http://download.java.net/jdk6/source/

 

    可见jvm的NIO使用的是linux 系统调用epoll模型;

 

4. java何时支持真正的AIO模型呢?

    JSR 203(http://jcp.org/en/jsr/detail?id=203) 在java SE 7.0中会完成JSR203.估计不久以后就可以普及了。asynchronous I/O对于java 绝对影响巨大,java写的网络服务器能够支持更大并发请求了。到时肯定大多网络服务器的I/O底层代码都会修改。就像当时Linux 2.6 支持AIO模型,很多数据库oracle,DB2都发布新版本。

分享到:
评论
6 楼 jarip 2013-12-10  
好文章,懂的人很多,又能写得这么好就难得了
5 楼 thrillerzw 2013-06-02  
向您学习,顶。
4 楼 623deyingxiong 2013-01-15  
有个问题:
1.我理解的异步I/O是:在C/S架构下,客户端发起请求后可以不用立刻等待服务端的应答,而是在未来某一时刻得到服务端的通知才去接收数据。NIO好像不能这样做吧?
2.NIO 在服务端,也是要手动用selector逐个扫描通道,检查是否有注册的事件发生,如果有再手动调用相应处理函数。这个过程中有事件驱动吗?如果是事件驱动就不用再自己写代码扫描通道了吧?

不知道我理解的对不对,希望能和楼主讨论一下。
3 楼 623deyingxiong 2013-01-15  
有个问题:1.我理解的异步I/O是:在C/S架构下,客户端发起请求后可以不用立刻等待服务端的应答,而是在未来某一时刻得到服务端的通知才去接收数据。NIO好像不能这样做吧?
2.NIO 在服务端,也是要手动用selector逐个扫描通道,检查是否有注册的事件发生,如果有再手动调用相应处理函数。这个过程中有事件驱动吗?如果是事件驱动就不用再自己写代码扫描通道了吧?

不知道我理解的对不对,希望能和楼主讨论一下。
2 楼 gogole_09 2011-05-25  
Nice ,    ,终于弄清楚了信号驱动式IO与AIO的区别
  区别在于  信号驱动IO通知什么时候可以进行IO操作,而aio则是通知什么时候完成io操作。
1 楼 洞玄的BLOG 2011-01-13  
楼主写的内容很好,把linux下的I/O模型讲的很很好,同时也介绍了NIO和NIO2,最近正在学习NIO相关的知识

相关推荐

    78程序员练级攻略(2018):异步IO模型和lock-Free编程1

    Libevent的《libevent 2.0 book》和《Libevent深入浅出》可以帮助理解其设计理念和使用方法,而Libuv的Design Overview提供了更详细的技术介绍。Reactor模式是处理大量并发连接的关键,它通过事件驱动的方式实现了非...

    深入浅出nodejs.pdf

    首先,Node.js的核心优势之一是其异步I/O模型。传统的Web应用模型中,对于I/O操作(如读写数据库、文件系统和网络请求等),大多数服务器端语言会采用同步方式,这意味着服务器在等待I/O操作完成时会阻塞线程,造成...

    竹林蹊径 深入浅出Windows驱动开发源码

    《竹林蹊径:深入浅出Windows驱动开发源码》是一部专为想要深入了解Windows驱动程序开发的工程师量身打造的指南。这本书通过丰富的实例和源码解析,带领读者步入驱动开发的世界,帮助他们掌握驱动程序的基本原理和...

    unix网络编程卷二

    《Unix网络编程卷二》深入浅出地解析了上述各种概念和技术,对于希望深入理解网络编程的开发者来说,是一本不可或缺的参考书。通过学习本书,读者可以掌握构建高效、稳定、可扩展的网络应用所需的关键技能。

    Node.js-StuQ分享专题《深入浅出jsNode.js异步流程控制》完整版

    本专题《深入浅出js(Node.js)异步流程控制》将探讨Node.js中的异步编程这一核心概念,帮助开发者更深入地理解和掌握这一技术。 异步编程是Node.js的核心特性之一,它允许程序在等待I/O操作完成时继续执行其他任务...

    深入浅出Linux设备驱动编程

    《深入浅出Linux设备驱动编程》是一本专为IT专业人士准备的深度技术指南,它涵盖了Linux设备驱动开发的多个核心领域。这本书旨在帮助读者理解如何有效地编写和优化Linux系统下的设备驱动程序,以实现硬件与操作系统...

    Asynchronous IO with Boost.Asio - Michael Caisse - CppCon 2016.pdf

    总结来说,文档“ASIO with Boost.Asio - Michael Caisse - CppCon 2016.pdf”深入浅出地介绍了Boost.Asio库,并通过具体的例子,详细阐释了异步I/O的工作原理和优势。对于希望掌握C++网络编程和异步编程的开发者来...

    深入浅出node.js 田永强著

    《深入浅出Node.js》是田永强撰写的一本关于Node.js技术的著作,全书共67页,旨在帮助读者全面理解并掌握Node.js这一强大的JavaScript运行环境。Node.js以其独特的事件驱动、非阻塞I/O模型,成为了构建高性能网络...

    深入浅出NETWORKING.pdf

    8. 性能优化:学习网络编程中常见的性能问题和优化策略,包括使用非阻塞I/O、选择合适的缓冲区大小、利用多线程或异步I/O提高吞吐量和响应能力。 9. 调试与测试:掌握网络编程中的调试技巧,了解如何使用网络抓包...

    深入浅出的

    2. 异步I/O:Node.js的API支持异步操作,大部分核心API如文件、网络等都是异步的,这样可以避免阻塞I/O操作影响程序的运行效率。 3. 轻量和高效:Node.js在设计上追求简洁,其内部实现高度抽象和封装,易于扩展和...

    深入浅出Netty ppt

    《深入浅出Netty》是针对Java网络编程框架Netty的一份详细讲解材料,由淘宝工程师精心制作,特别适合初学者。Netty是一款高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。...

    深入浅出Nodejs(朴灵)

    《深入浅出Node.js》是由朴灵编著的一本关于Node.js技术的权威教程,它旨在帮助读者深入理解Node.js的核心原理与实践应用。这本书详细介绍了Node.js的基础知识、核心特性以及如何构建高性能的Web应用。 Node.js是...

    深入浅出JavaScript(jb51.net).pdf

    异步编程是JavaScript的另一大挑战,书中会详细解释回调函数、Promise和async/await等非阻塞I/O模型。随着Web应用的复杂性增加,掌握异步编程技巧是必不可少的。 最后,书中可能还会涵盖ES6(ECMAScript 2015)及...

    vc++网络编程电子书

    在本书中,作者深入浅出地介绍了网络编程的各个方面,包括TCP/IP协议、套接字编程、多线程技术以及异步I/O模型等核心主题。 首先,书中详细讲解了网络通信的基础,如TCP/IP协议栈的工作原理,涵盖了IP地址、端口号...

    深入浅出nodejs

    其次,深入解析“事件循环(Event Loop)”:这是Node.js异步I/O模型的基础,也是其高并发能力的关键。事件循环监听并处理各种事件,如定时器、网络请求、文件操作等。理解事件循环的工作原理至关重要,包括事件队列...

    《Node即学即用》 Node, Up and Running 原版

    而Node.js通过异步I/O避免了这一问题,使得它可以处理更多的请求而不降低响应速度。 - **事件驱动编程模型**:Node.js的核心是事件循环,所有的网络和文件系统操作都通过回调函数实现。这种模型减少了阻塞的可能性,...

    深入浅出javascript源代码

    4. **异步编程**:JavaScript的非阻塞I/O模型使得异步编程成为必须。事件循环、回调函数、Promise和async/await等概念是处理异步操作的核心。通过源代码,你可以看到如何有效地编写异步代码以避免回调地狱。 5. **...

Global site tag (gtag.js) - Google Analytics