`
csd_ali
  • 浏览: 133635 次
  • 性别: 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相关的知识

相关推荐

    高性能IO模型浅析

    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型。 (2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非...深入浅出介绍这几种模型

    《Windows网络编程技术》高清PDF版+随书源码

    本书论述深入浅出、用大量实例详解了微软网络API函数的应用。配套光盘包含了所有实例代码,方便读者使用。本书适合中、高级程序设计人员以及网络设计与管理人员参考。包 装: 平装本书通过应用实例由浅入深引入VC++...

    WINDOWS网络编程技术.pdf

    本书论述深入浅出、用大量实例详解了微软网络API函数的应用。配套光盘包含了所有实例代码,方便读者使用。本书适合中、高级程序设计人员以及网络设计与管理人员参考。包 装: 平装本书通过应用实例由浅入深引入VC++...

    《WINDOWS网络编程技术》

    本书专门讨论Windows网络编程技术,覆盖Windows 95/98/NT 4/2000/CE平台,内容包括NetBIOS和Windows重定向器方法、Winsock方法、客户端远程访问服务器方法,本书论述深入浅出、用大量实例详解了微软网络API函数的...

    asp.net知识库

    深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中的私有变量 关于反射中创建类型实例的两种方法 ASP.Net应用程序的多进程模型 NET委托...

Global site tag (gtag.js) - Google Analytics