文档章节

再谈select, iocp, epoll,kqueue及各种I/O复用机制

开心303
 开心303
发布于 2012/02/09 14:33
字数 1101
阅读 279
收藏 5

首先,介绍几种常见的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)

blocking I/O 
这个不用多解释吧,阻塞套接字。下图是它调用过程的图示:

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

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

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

I/O multiplexing (select and poll) 
最常见的I/O复用模型,select。

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

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

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

asynchronous I/O (the POSIX aio_functions) 
很少有*nix系统支持,windows的IOCP则是此模型

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

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

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

=====================分割线==================================

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

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

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

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

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

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

提供一致的接口,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复用机制的封装。

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模型。。

© 著作权归作者所有

开心303
粉丝 142
博文 88
码字总数 106265
作品 0
闵行
CTO(技术副总裁)
私信 提问
select,iocp,epoll,kqueue及各种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)......

大道至簡
2014/08/04
0
1
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) b......

linuxprobe
2016/09/24
7
0
【转】网络编程模型综述 之 成熟的IO框架介绍

分类: linux网络编程 | 标签: |字号大中小 订阅 ACE “重量级的C++ I/O框架,用面向对象实现了一些I/O策略和其它有用的东西,特别是它的Reactor是用OO方式处理非阻塞I/O,而Proactor是用O...

javabird
2012/07/20
0
1
Nginx为什么比Apache Httpd高效:原理篇

Nginx才短短几年,就拿下了web服务器大笔江山,众所周知,Nginx在处理大并发静态请求方面,效率明显高于httpd,甚至能轻松解决C10K问题。下面我们就来聊聊Web服务器背后的一些原理。 一、进程...

小杨_Ivan
2017/02/09
0
0
Socket编程模式理解与对比

本文主要分析了几种Socket编程的模式。主要包括基本的阻塞Socket、非阻塞Socket、I/O多路复用。其中,阻塞和非阻塞是相对于套接字来说的,而其他的模式本质上来说是基于Socket的并发模式。I...

xumaojun
2018/05/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

微服务之架构技术选型与设计

本文主要介绍了架构技术选型与设计-微服务选型,Spring cloud 实现采用的技术,希望对您的学习有所帮助。 架构技术选型与设计-DUBBODubbo,是阿里巴巴服务化治理的核心框架,并被广泛应用于阿...

别打我会飞
38分钟前
3
0
在Windows中运行Linux bash命令的几种方法

如果你正在课程中正在学习 shell 脚本,那么需要使用 Linux 命令来练习命令和脚本。 你的学校实验室可能安装了 Linux,但是你自己没有安装了 Linux 的笔记本电脑,而是像其他人一样的 Window...

老孟的Linux私房菜
40分钟前
6
0
深入理解计算机系统(1.1)------Hello World 是如何运行的

上一篇序章我谈了谈 程序员为啥要懂底层计算机结构 ,有人赞同也有人反对,但是这并不影响 LZ 对深入理解计算机系统研究的热情。这篇博客以案例驱动的模式,通过跟踪一个简单 Hello World 程...

vinci321
46分钟前
2
0
Linux操作系统之Shell程序设计

Linux操作系统之Shell程序设计 Shell是种命令解释程序,也可以看作是一种命令语言的解释器。 用户在与Shell交互时所输入的命令行必须符合Shell命令的语法和语义规范,才能够被Shell理解并执行...

linuxCool
53分钟前
5
0
Java Foreach拉姆达表达式

以下案例分析了foreach循环和Java8 拉姆达表达式的区别 public static void main(String[] args) {/* * foreach 和 list */List<String> arrs = new ArrayList<>();...

cuishy
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部