写在前面:本文整理于知乎,原文链接为http://www.zhihu.com/question/32163005/answer/55772739,作者:罗志宇

再次向作者表示感谢~~

假设你是一个机场的空管, 你须要管理到你机场的全部的航线。 包含进港,出港, 有些航班须要放到停机坪等待,有些航班须要去登机口接乘客。

你会怎么做?

那么问题就来了:

非常快你就发现空管塔里面聚集起来一大票的空管员,交通略微繁忙一点,新的空管员就已经挤不进来了。

空管员之间须要协调,屋子里面就1, 2个人的时候还好,几十号人以后 。基本上就成菜市场了。

空管员常常须要更新一些公用的东西。比方起飞显示屏,比方下一个小时后的出港排期。最后你会非常惊奇的发现,每个人的时间最后都花在了抢这些资源上。

现实上我们的空管同一时候管几十架飞机稀松寻常的事情, 他们怎么做的呢?

他们用这个东西

   ![这里写图片描写叙述](https://pic2.zhimg.com/583d5ba3cee12e78befa8e2b749f4269_b.jpg)

这个东西叫flight progress strip. 每个块代表一个航班,不同的槽代表不同的状态,然后一个空管员能够管理一组这种块(一组航班),而他的工作。就是在航班信息有新的更新的时候。把相应的块放到不同的槽子里面。

这个东西如今还没有淘汰哦,仅仅是变成电子的了而已。

是不是认为一下子效率高了非常多,一个空管塔里能够调度的航线能够是前一种方法的几倍到几十倍。

假设你把每个航线当成一个Sock(I/O 流), 空管当成你的服务端Sock管理代码的话.

第一种方法就是最传统的多进程并发模型 (每进来一个新的I/O流会分配一个新的进程管理。)

另外一种方法就是I/O多路复用 (单个线程,通过记录跟踪每个I/O流(sock)的状态,来同一时候管理多个I/O流 。

)

事实上“I/O多路复用”这个坑爹翻译可能是这个概念在中文里面如此难理解的原因。所谓的I/O多路复用在英文中事实上叫 I/O multiplexing. 假设你搜索multiplexing啥意思,基本上都会出这个图:



于是大部分人都直接联想到”一根网线。多个sock复用” 这个概念,包含上面的几个回答。 事实上无论你用多进程还是I/O多路复用。 网线都仅仅有一根好伐。多个Sock复用一根网线这个功能是在内核+驱动层实现的。

重要的事情再说一遍: I/O multiplexing 这里面的 multiplexing 指的事实上是在单个线程通过记录跟踪每个Sock(I/O流)的状态(相应空管塔里面的Fight progress strip槽)来同一时候管理多个I/O流. 发明它的原因,是尽量多的提高server的吞吐能力。

是不是听起来好拗口,看个图就懂了.



在同一个线程里面, 通过拨开关的方式。来同一时候传输多个I/O流。 (学过EE的人如今能够站出来义正严辞说这个叫“时分复用”了)。

什么,你还没有搞懂“一个请求到来了,nginx使用epoll接收请求的过程是如何的”。 多看看这个图就了解了。

提醒下,ngnix会有非常多链接进来, epoll会把他们都监视起来,然后像拨开关一样。谁有数据就拨向谁。然后调用相应的代码处理。

------------------------------------------

了解这个主要的概念以后,其它的就非常好解释了。

select, poll, epoll 都是I/O多路复用的详细的实现。之所以有这三个鬼存在,事实上是他们出现是有先后顺序的。

I/O多路复用这个概念被提出来以后。 select是第一个实现 (1983 左右在BSD里面实现的)。

select 被实现以后,非常快就暴露出了非常多问题。

select 会改动传入的參数数组。这个对于一个须要调用非常多次的函数,是非常不友好的。

select 假设不论什么一个sock(I/O stream)出现了数据,select 仅仅会返回,但是并不会告诉你是那个sock上有数据,于是你仅仅能自己一个一个的找,10几个sock可能还好。要是几万的sock每次都找一遍,这个无谓的开销就颇有海天盛筵的豪气了。

select 仅仅能监视1024个链接。 这个跟草榴没啥关系哦。linux 定义在头文件里的,參见FD_SETSIZE。

select 不是线程安全的,假设你把一个sock增加到select, 然后突然另外一个线程发现。尼玛。这个sock不用。要收回。对不起。这个select 不支持的,假设你丧心病狂的居然关掉这个sock, select的标准行为是。。

呃。。不可预測的, 这个但是写在文档中的哦.

“If a file descriptor being monitored by select() is closed in another thread, the result is unspecified”

霸不霸气

于是14年以后(1997年)一帮人又实现了poll, poll 修复了select的非常多问题,比方

poll 去掉了1024个链接的限制,于是要多少链接呢, 主人你开心就好。

poll 从设计上来说。不再改动传入数组,只是这个要看你的平台了,所以行走江湖。还是小心为妙。

事实上拖14年那么久也不是效率问题, 而是那个时代的硬件实在太弱,一台server处理1千多个链接简直就是神一样的存在了,select非常长段时间已经满足需求。

但是poll仍然不是线程安全的, 这就意味着,无论server有多强悍。你也仅仅能在一个线程里面处理一组I/O流。你当然能够那多进程来配合了,只是然后你就有了多进程的各种问题。

于是5年以后, 在2002, 大神 Davide Libenzi 实现了epoll.

epoll 能够说是I/O 多路复用最新的一个实现,epoll 修复了poll 和select绝大部分问题, 比方:

epoll 如今是线程安全的。

epoll 如今不仅告诉你sock组里面数据,还会告诉你详细哪个sock有数据,你不用自己去找了。

epoll 当年的patch,如今还在,以下链接能够看得到:

/dev/epoll Home Page

贴一张霸气的图。看看当年神一样的性能(測试代码都是死链了。 假设有人能够刨坟找出来。能够研究下细节怎么測的).



横轴Dead connections 就是链接数的意思。叫这个名字仅仅是它的測试工具叫deadcon. 纵轴是每秒处理请求的数量,你能够看到。epoll每秒处理请求的数量基本不会随着链接变多而下降的。poll 和/dev/poll 就非常慘了。

但是epoll 有个致命的缺点。

。仅仅有linux支持。

比方BSD上面相应的实现是kqueue。

事实上有些国内知名厂商把epoll从安卓里面裁掉这种脑残的事情我会主动告诉你嘛。

什么,你说没人用安卓做server。尼玛你是看不起p2p软件了啦。

而ngnix 的设计原则里面, 它会使用目标平台上面最高效的I/O多路复用模型咯,所以才会有这个设置。普通情况下,假设可能的话,尽量都用epoll/kqueue吧。

详细的在这里:

Connection processing methods

PS: 上面全部这些比較分析。都建立在大并发以下。假设你的并发数太少,用哪个,事实上都没有差别。

假设像是在欧朋数据中心里面的转码server那种动不动就是几万几十万的并发,不用epoll我能够直接去撞墙了。

作者:罗志宇

链接:http://www.zhihu.com/question/32163005/answer/55772739

来源:知乎

著作权归作者全部。商业转载请联系作者获得授权,非商业转载请注明出处。

Linux IO 多路复用是什么意思?的更多相关文章

  1. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

  2. Linux IO多路复用 poll

    Linux IO多路复用 poll 之前曾经提到过 select poll 跟select类似,poll改进了select的一个确定,就是poll没有监听上限 不过poll还是需要遍历以及频繁的把数组 ...

  3. Linux IO多路复用 select

    Linux IO多路复用 select 之前曾经写过简单的服务器,服务器是用多线程阻塞,客户端每一帧是用非阻塞实现的 后来发现select可以用来多路IO复用,就是说可以把服务器这么多线程放在一个线程 ...

  4. Linux IO多路复用

    监听文件描述符的状态来进行相应的读写操作,3个函数: 123 selectpollepoll 123456789 int (int nfds, fd_set *readfds, fd_set *wri ...

  5. Linux IO多路复用之epoll网络编程及源码(转)

    原文: 前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网 ...

  6. linux IO多路复用POLL机制深入分析

    POLL机制的作用这里就不进行介绍,根据linux man手册,解释为在一个文件描述符上等待某个事件.按照抽象一点的理解,当某个事件被触发(条件被满足),文件描述符变为有状态,那么用户空间可以根据此进 ...

  7. Linux IO多路复用之epoll网络编程(含源码)

    前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...

  8. Linux IO多路复用之epoll网络编程

    前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网络读取一 ...

  9. Linux IO多路复用 select/poll/epoll

    Select -- synchronius I/O multiplexing select, FS_SET,FD_CLR,FD_ISSET,FD_ZERO #include <sys/time. ...

随机推荐

  1. MySQL本地登录及数据库导入导出

    注意:本地MySQL服务要开启 更新整个数据库 1.将正式服务器上的数据库做备份 登录到正式服务器,执行如下命令:(注意空格) mysqldump -uroot –p密码 数据库名 -P 接口 --d ...

  2. 测试网站链接是否可用(wget和curl)

    一.wget用法案例 系统给的命令参数如下: [root@litong_centos mysql3307]# wget --help GNU Wget 1.14, a non-interactive ...

  3. timeslot概念(还是不太懂呀!!)

    rules: 1. event.triggered只会保持一个time_slot,在下一个time_slot将会丢失这个标记,如果不能保证在每一个time_slot都会检测到这个标志,那么将会丢失这个 ...

  4. Android开发——查询/杀死手机里正在运行的进程

    0. 前言 以前有同学好像做过一个叫"自习君"的App,开启后自动检测用户这一天的自习时间,在学校里宣传广告还打了不少.其实实现原理非常简单,在SQlite数据库(也可以通过文件) ...

  5. (转)]PYTHON Tkinter GUI

    import Tkinterroot=Tkinter.Tk()label=Tkinter.Label(root,text='hello ,python')label.pack()      #将LAB ...

  6. 分享14个很酷的jQuery导航菜单插件

    导航按钮是网站的非常重要的一部分,因其将网站的所有部分而集中一处,jQuery导航菜单插件在其中扮演重要的角色. 本文介绍了14个很酷的jQuery导航菜单插件,它们够漂亮.简单,并且完全兼容各种类型 ...

  7. 安装SecureCRT注册

    注册方法 1.首先运行压缩包中的安装程序进行安装原版程序!2.安装完成后记得先不要运行程序!3.复制压缩包中的keygen.exe程序到安装目录!4.运行keygen.exe,点击Patch按钮对源程 ...

  8. Go切片基础

    package main import "fmt" //切片(Slice)本身没有数据,是对底层Array的一个view //不使用指针就可以改数组内容 //slice可以向后扩展 ...

  9. [luoguP1186] 玛丽卡(spfa)

    传送门 因为要随机删除一条边,而枚举所有边肯定会超时,经过发现,先求出一遍最短路,而要删除的边肯定在最短路径上,删除其他的边对最短路没有影响. 所以可以先求出最短路,再枚举删除最短路上的每一条边再求最 ...

  10. BZOJ:[JSOI2009]游戏Game【二分图匹配乱搞】

    题目大意:n*m的棋盘,其中有些区域是禁区,两个人在棋盘上进行博弈,后手选择棋子的初始位置,然后先后手轮流将棋子往上下左右移动,走过的区域不能再走,问能否有一个位置使得后手必胜 Input 输入数据首 ...