参考原文:再谈select, iocp, epoll,kqueue及各种I/O复用机制

一、I/O模型概述

  介绍几种常见的I/O模型及其区别,如下:

  • blocking I/O

  • nonblocking I/O

  • I/O multiplexing (select and poll)

  • signal driven I/O (SIGIO)

  • asynchronous I/O (the POSIX aio_functions)

(1)blocking I/O 
  阻塞式套接字。下图是它调用过程的图示:

  重点解释下上图,首先application调用 recvfrom()转入kernel,注意kernel有2个过程,wait for data和copy data from kernel to user。直到最后copy complete后,recvfrom()才返回。此过程一直是阻塞的。

(2)nonblocking I/O: 
  与blocking I/O对立的,非阻塞套接字,调用过程图如下:

  可以看见,如果直接操作它,那就是个轮询。。直到内核缓冲区有数据。

(3)I/O multiplexing (select and poll) 
  最常见的I/O复用模型,select模型/poll模型,两者原理和数据结构均类似。

  select/poll先阻塞,有活动套接字才返回。与blocking I/O相比,select/poll会有两次系统调用,但是select/poll能处理多个套接字。

(4)signal driven I/O (SIGIO) 
  只有UNIX系统支持,感兴趣的课查阅相关资料。

  与I/O multiplexing (select and poll)相比,它的优势是,免去了select的阻塞与轮询,当有活跃套接字时,由注册的handler处理。

(5)asynchronous I/O (the POSIX aio_functions,真正意义上的异步IO) 
  很少有*nix系统支持,windows的IOCP则是此模型。

  完全异步的I/O复用机制,因为纵观上面其它四种模型,至少都会在由kernel copy data to appliction时阻塞。而该模型是当copy完成后才通知application,可见是纯异步的。好像只有windows的完成端口是这个模型,效率也很出色。

下面是以上五种模型的比较

  可以看出,越往后,阻塞越少,理论上效率也是最优。

二、实际模型分析

  上述5种模型的比较比较清晰了,剩下的就是把select,epoll,iocp,kqueue按号入座。

  select和iocp分别对应第3种与第5种模型,那么epoll与kqueue呢?其实也于select属于同一种模型,只是更高级一些,可以看作有了第4种模型的某些特性,即callback机制。

2.1 为什么epoll,kqueue比select高级? 

  答案是,他们轮询。因为他们用callback取代了。想想看,当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll与kqueue做的。

2.2 windows or *nix (IOCP or kqueue/epoll)?

  诚然,Windows的IOCP非常出色,目前支持asynchronous I/O的系统并不多,但是由于操作系统本身的局限性,大型服务器还是在*NIX下。而且正如上面所述,kqueue/epoll 与 IOCP相比,就是多了一层从内核copy数据到应用层的阻塞,从而不能算作asynchronous I/O类。但是,这层小小的阻塞无足轻重,kqueue与epoll已经做得很优秀了。

2.3 提供一致的接口,IO Design Patterns

  实际上,不管是哪种模型,都可以抽象一层出来,提供一致的接口,广为人知的有ACE,Libevent这些,他们都是跨平台的,而且他们自动选择最优的I/O复用机制,用户只需调用接口即可。说到这里又得说说2个设计模式,Reactor and Proactor。有一篇经典文章http://www.artima.com/articles/io_design_patterns.html值得阅读,Libevent是Reactor模型,ACE提供Proactor模型。实际都是对各种I/O复用机制的封装。

2.4 Java nio包是什么I/O机制?

  我曾天真的认为java nio封装的是IOCP。。现在可以确定,目前的java本质是select()模型,可以检查/jre/bin/nio.dll得知。至于java服务器为什么效率还不错。。我也不得而知,可能是设计得比较好吧。。-_-。

小结:

  1. 只有IOCP是asynchronous I/O,其他机制或多或少都会有一点阻塞。
  2. select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善
  3. epoll, kqueue是Reacor模式,IOCP是Proactor模式。
  4. java nio包是select模型。。

最新文章

  1. css中的一些属性解析
  2. Python Django 数据库操作
  3. 测试dockerfile
  4. Linux学习笔记21——线程同步的两种方式
  5. ElasticSearch实战
  6. AndroidManifest.xml file missing 解决方案
  7. 使用Spring Boot开发Web项目
  8. Swift下多个Storyboard的项目结构
  9. C#实现联通短信Sgip协议程序源码
  10. SmartUpload工具包的中文乱码问题详解
  11. 用PIL库进行图像处理
  12. 在学习JavaScript中用到的示例
  13. T-SQL :SQL Server系统数据库(二)
  14. 【vue】vue +element 搭建项目,$createElement使用
  15. Codeforces 362D Fools and Foolproof Roads
  16. 虚方法virtual、抽象方法abstract、接口interface区别
  17. mysql-The-server-quit-without-updating-PID-file
  18. 解决iPad/iPhone下手机号码会自动被加上a标签的问题
  19. TreeListControl:设置行样式
  20. sqldataAdapter/dataset/datatable的使用

热门文章

  1. EL 表达式 取值将 < 转成 &1t 问题
  2. Debian 入门安装与配置1
  3. (基础篇)PHP与Web页面交互
  4. SecureCRT最佳配色方法+直接修改默认配置方法 - imsoft.cnblogs
  5. Log4J 使用实战
  6. tyvj 1049 最长不下降子序列 n^2/nlogn
  7. JavaScript的一些认识
  8. Android滑动选择的日期选择框
  9. 3-1 rpm包命名规则
  10. 最短路--floyd算法模板