一、select

1.起源

select最早于1983年出现在4.2BSD中(BSD是早期的UNIX版本的分支)。

它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。

2.select的优点

目前几乎在所有的平台上支持,具有良好的跨平台支持。

3.select的缺点

  1. 单个进程能够监视的文件描述符的数量存在最大限制。默认情况下,在Linux上单个进程能够打开的最大文件数为1024.(可以通过修改宏定义甚至重新编译内核的方式提升这一限制)。
  2. select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大, 其复制的开销也线性增长。
  3. 由于网络相应时间的延迟使得大量的TCP连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,浪费了一定的开销。
  4. select()所维护的socket连接,kernel中有数据了只会返回称有数据了,但不会指定socket,还需要对socket进行扫描,找到是哪些socket在kernel中准备了数据,浪费了开销。

二、poll

1.起源

poll在1986年诞生于System V Release 3,它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。

2.poll的优点

没有最大文件描述符数量的限制。

3.poll的缺点

  1. 包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
  2. poll将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用poll()的时候将再次报告这些文件描述符,所以poll()一般不会丢失就绪的信息,这种方式成为 水平触发Level Triggered.

4.poll的实际应用

在实际中,poll被认为是select,poll,epoll之间的一个过渡阶段,在实际中运用不多。

 

三、epoll

1.起源

epoll是在Linux2.6中提出的,是之前的select和poll的增强版本。

2.epoll的优点

相对于select和poll来说,epoll更加灵活,没有描述符限制。

epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

epoll是由内核直接支持的实现方法,它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。epoll是目前最流行的,目前知名框架Tornado,Nginx,Twisted等都是使用的epoll。

  1. epoll更加灵活,没有描述符限制。
  2. epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
  3. epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。
  4. 另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。
如:epoll监控着100个socket,交给kernel去监测,如果kernel发现只有两个socket有数据,那么kernel会告诉用户具体是哪一个socket有数据,只需要循环去这两个活跃的socket中收取数据,节省了这部分的开销。

  注:水平触发和边缘触发(Level Triggered and Edge Triggered)

  水平触发Level Triggered:在kernel中数据准备好,处于ready的状态,如果进程没有对其进行IO操作,数据就还是在kernel中,只有进程再次发送一个recvfrom(system call),触发后才会将kernel中的就绪的数据拷贝到用户内存中去。

  边缘触发Edge Triggered:和水平触发相反,数据在kernel中ready后,如果进程没有对其进行IO操作,那么就不会再次return readable等信息给进程。数据还是在kernel中,并不会到用户内存中去。

3.epoll的缺点

仅在支持2.6内核的平台中支持。

Windows 不支持epoll,支持select。

四、select的代码实现

需求:用select实现一个简单的socketserver,可以实现多并发。

I/O多路复用之select,poll,epoll简介的更多相关文章

  1. IO多路复用之select poll epoll

    参考文档: http://blog.csdn.net/tennysonsky/article/details/45745887 select(),poll(),epoll()都是I/O多路复用的机制. ...

  2. Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)

    Linux下测试代码: http://www.linuxhowtos.org/C_C++/socket.htm TCP模型 //TCPClient.c #include<string.h> ...

  3. 浅谈网络I/O多路复用模型 select & poll & epoll

    http://blog.csdn.net/nk_test/article/details/50662946

  4. Select/Poll/Epoll异步IO

    IO多路复用 同步io和异步io,阻塞io和非阻塞io分别是什么,有什么样的区别? io模式 对于一次io 访问(以read为例),数据会先拷贝到操作系统内核的缓冲区,然后才会从操作系统内核的缓冲区拷 ...

  5. Linux IO模式以及select poll epoll详解

    一 背景 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的network ...

  6. 转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】

    下面这篇,原理理解了, 再结合 这一周来的心得体会,整个框架就差不多了... http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架, ...

  7. IO多路复用select/poll/epoll详解以及在Python中的应用

    IO multiplexing(IO多路复用) IO多路复用,有些地方称之为event driven IO(事件驱动IO). 它的好处在于单个进程可以处理多个网络IO请求.select/epoll这两 ...

  8. Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程

    1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...

  9. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

随机推荐

  1. python爬虫之requests的高级使用

    1.requests能上传文件 # 导入requests模块 import requests # 定义一个dict files = {'file': open('D:/360Downloads/1.t ...

  2. Java Object类学习总结

    这篇博文发出来总有点问题,转为图片了,谢谢看官支持.

  3. 原地算法(in-place algorithm)

    原地算法(in-place algorithm) 在计算机科学中,一个原地算法(in-place algorithm)基本上不需要额外辅助的数据结构,然而,允许少量额外的辅助变量来转换数据的算法.当算 ...

  4. (js描述的)数据结构[链表](4)

    (js描述的)数据结构 [链表](4) 一.基本结构 二.想比于数组,链表的一些优点 1.内存空间不是必须连续的,可以充分利用计算机的内存,事项灵活的内存动态管理. 2.链表不必再创建时就确定大小,并 ...

  5. docker-compose 部分错误

    Get https://hub.17kxkx.com/v2/: dial tcp 39.106.209.67:443: connect: connection refused vim /etc/doc ...

  6. Jdk 和 jre 的 关系和区别

    Jdk 和 jre 的 关系和区别 区别: JDK:是Java Development Kit 的简称–>翻译过来就是:Java 开发工具包.是程序员使用java语言编写java程序所需的开发工 ...

  7. 8.4 StringBuilder的介绍及用法(String 和StringBuilder区别)

    * StringBuilder:是一个可变的字符串.字符串缓冲区类.** String和StringBuilder的区别:* String的内容是固定的.(方法区的内容)* StringBuilder ...

  8. matlab操作Excel数据

    sheet是Excel的表格,xIRange是表格的列的范围 指定xlRange,例如使用语法'C1:C2',其中C1和C2是定义要读取的区百域的两个度相对的角. 例如,'D2:H4'表示工作表上的两 ...

  9. 胜利大逃亡 BFS

    Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0 ...

  10. CKEditor与定制

    一 开始使用 官网 基本示例: 搭建服务器(这里使用apache) 下载standard的ckeditor解压放在apache的htdocs的目录下 在htdoc下面新建index.html,写入代码 ...