select、poll、epoll的区别总结

select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作

但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间

三组IO复用函数的比较

select:

select系统调用的用途是:在一段指定时间内,监听用户所感兴趣的文件描述符上的可读、可写和异常事件

缺点:

1.所能监视的文件描述符的数量有限制,sizeof(fd_set)=128,说明能监视的描述符的最大值为128*8=1024个

2.同时每次调用select都需要在内核遍历传递进来的所有fd,当fd很多时性能会下降

3.由于当有事件发生时,select返回后会修改三个事件集,所以,每次都需要把fd集合从用户区拷贝到内核区,当需要监视的fd数量增多时,性能会下降

适用场景:

适用于所监视的文件描述符数量较少的场景

poll:

poll系统调用和select类似,也是在制定时间内轮询一定数量的文件描述符,以测试其中是否有就绪的文件描述符

优点:

1.相比select来讲,它没有fd数量的限制,理论上打开fd的数目跟系统内在有关

2.也不用每次都把fd集合从用户区拷贝数据到内核,它使用一个  struct pollfd结构体来维护每个fd

缺点:

它本质上是和selece一样的,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多

适用场景:

也适用于所监视文件描述符少的场景

epoll:

epoll是Linux特有的IO复用函数,被认为性能最好的一种方法,

它和select、poll在实现和使用上有很大差异:

1.使用一组函数来完成,而不是单个

2. 把用户关心的文件描述符上的事件放在内核的一个事件表中,无须向select、poll那样每次调用都要重复传入文件描述符集或事件集,但epoll需要用一个额外的文件描述符来表示内核中的这个事件表

epoll函数非常简单,有epoll_create,epoll_ctl,epoll_wait3个函数,先使epoll_create创建一个epoll的句柄,再通过epoll_ctl注册事件,然后epoll_wait检测事件的发生

优点:

具备了select所不具备的所有优点

1.没有fd数量的限制,它所支持的fd上限是最大可以打开文件的数目,具体数目可cat/proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大

2.epoll_ctl每次注册新的事件到epoll句柄中时(在epoll_ctl中指定EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝,epoll保证了每个fd在整个过程中只会拷贝一次

3.epoll的解决方案不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd

适用场景:

当活动连接比较多的时候,epoll_wait的效率未必比select和poll高,因为此时回调函数被触发的过于频繁,因此epoll_wait适用于连接数量多,但活动连接较少的情况

epoll对文件描述符的操作有两种模式:LT和ET

LT(水平触发):这种模式是默认的工作模式,此时,epoll相当于效率较高的poll,

当往epoll内核事件表中注册一个文件描述符上的EPOLLET事件时,epoll将以ET模式来操作该文件描述符

ET(边沿触发):ET模式是epoll的高效工作模式,它在很大程度上降低了同一个epoll事件被重复触发的次数


总结:

这3组IO复用系统调用都能同时监听多个文件描述符,它们将等待由timeout参数指定的超时时间,直到一个或者多个文件描述符上有时间发生时返回,返回值就是就绪的文件描述符的数量,返回0表示没有事件发生。

这3组函数都通过某种结构体变量来告诉内核监听哪些文件描述符上的那些事件,并使用该结构体类型的参数来获取内核处理的结果。

select的参数类型fd_set,没有将文件描述符集合事件绑定,它仅仅是一个文件描述符集合,因此select需要提供3个这种类型的参数来分别传入和输出可读可写异常事件,这一方面使得select不能处理更多类型的事件,另一方面由于内核对fd_set集合的在线修改,应用程序下次调用select前不得不重置这3个fd_set集合。

poll的参数类型pollfd,它把文件描述符和事件都定义其中,任何事件都被统一处理,从而使编程接口简洁的多。并且内核每次修改的是pollfd结构体的revents成员,而events成员保持不变,因此下次调用poll时应用程序无须重置pollfd类型的事件集。

epoll使用一个独立的系统调用epoll_ctl来控制往其中添加、修改、删除事件。这样每次epoll_wait调用都直接从该内核事件表中取得用户注册的时间,而无须反复从用户空间读入这些事件,epoll_wait系统调用的events参数仅用来返回就绪的事件,这使得应用程序索引就绪文件描述符的时间复杂度达到O(1)。

poll和epoll_wait分别用nfds和maxevents参数指定最多监听多少个文件描述符和事件,这两个数值都能达到系统允许打开的最大文件描述符数目,我的系统下是48428

而select允许监听的文件描述符数量通常是有限的,测试结果为128*8=1024个

select和poll都只能工作在相对低效的LT模式下,而epoll则可以工作在ET高效模式,并且epoll还支持EPOLLONESHOT事件,该事件能进一步减少可读、可写和异常事件被触发的次数。

select采用的都是轮询的方式,即每次调用都要扫描整个注册文件描述符集合,epoll_wait采用的是回调的方式,内核检测到就绪的文件文件描述符时,将触发回调函数,回调函数就将该文件描述符上对应的事件插入内核就绪事件队列。内核最后在适当的时机将该就绪事件队列中的内容拷贝到用户空间,因此epoll无需轮询整个文件描述符集合来检测哪些事件已经就绪,当活动连接比较多的时候,epoll_wait的效率未必比select和poll高,因为此时回调函数被触发的过于频繁,因此epoll_wait适用于连接数量多,但活动连接较少的情况。

《完》

时间: 2024-10-26 20:32:49

select、poll、epoll的区别总结的相关文章

python select poll epoll的区别

select 优点:为最早的异步io处理模块,他可以再linux上和windows上使用,跨平台兼容性好,而poll和epoll都不能在windows系统环境中使用. 缺点:select的机制决定了他每次循环需要对所有input中的端口进行检测,看是否有新连接建立.他的开销会随所检测端口数量线性增大.且他的最大检测数为1024(可以修改). poll:他的机制和select相同,所以也造成了检测的端口越多,他的开销越大,且不能在windows下面使用.但是他没有检测的最大限制 epoll:采用新

Linux内核中网络数据包的接收-第二部分 select/poll/epoll

和前面文章的第一部分一样,这些文字是为了帮别人或者自己理清思路的,而不是所谓的源码分析,想分析源码的,还是直接debug源码最好,看任何文档以及书都是下策.因此这类帮人理清思路的文章尽可能的记成流水的方式,尽可能的简单明了. Linux 2.6+内核的wakeup callback机制 Linux 内核通过睡眠队列来组织所有等待某个事件的task,而wakeup机制则可以异步唤醒整个睡眠队列上的task,每一个睡眠队列上的节点都拥有一个 callback,wakeup逻辑在唤醒睡眠队列时,会遍历

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

详细说说select poll epoll

(以下内容来自网络和自己的总结,再次感谢网络中的大神们提供的见解) 在探索select poll  epoll之前我们首先要知道什么叫多路复用: 下来探索一下为什么会用到多路复用: 首先我们看看一个客户端请求服务器的完整过程.首先,请求过来,要建立连接,然后再接收数据,接收数据后,再发送数据. 具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作,如果不用非阻塞的方式来调用,那就得阻塞调用了,事件没有准备好,那就只能等了,等事件准备好了,你再继续吧.阻塞调用会进入内核等待,cpu

select,poll,epoll用法

http://blog.csdn.net/sunboy_2050/article/details/6126712 select用法 #include <sys/time.h>       #include <sys/types.h>       #include <unistd.h> #include <sys/select.h> int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exc

Linux I/O复用中select poll epoll模型的介绍及其优缺点的比较

关于I/O多路复用: I/O多路复用(又被称为"事件驱动"),首先要理解的是,操作系统为你提供了一个功能,当你的某个socket可读或者可写的时候,它可以给你一个通知.这样当配合非阻塞的socket使用时,只有当系统通知我哪个描述符可读了,我才去执行read操作,可以保证每次read都能读到有效数据而不做纯返回-1和EAGAIN的无用功.写操作类似.操作系统的这个功能通过select/poll/epoll之类的系统调用来实现,这些函数都可以同时监视多个描述符的读写就绪状况,这样,**多

select,poll,epoll的归纳总结区分

Select.Poll与Epoll比较 以下资料都是来自网上搜集整理.引用源详见文章末尾. 1 Select.Poll与Epoll简介 Select select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理.这样所带来的缺点是: 1 单个进程可监视的fd数量被限制 2 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大 3 对socket进行扫描时是线性扫描 Poll poll本质上和select没有区别,它将用户传入的数组拷贝到内核

IO复用之select poll epoll的总结

I/O复用使得程序能够同时监听多个文件描述符,对于提高程序性能至关重要.I/O复用不仅仅在网络程序中使用,但是我接触到的例子中,TCP网络编程那块使用I/O复用比较多,例如,TCP服务器同时处理监听socket和连接socket. 在了解I/O复用之前,我们需要先了解几个概念. 1,同步I/O与异步I/O 2,LT(水平触发)和ET(边缘触发) POSIX把两个术语定义如下: 同步I/O:导致请求进程阻塞,直到I/O操作完成 异步I/O:  不导致请求进程阻塞 阻塞是进程在等待某种资源,但是不能

Linux下select&amp;poll&amp;epoll的实现原理(一)

最近简单看了一把Linux linux-3.10.25 kernel中select/poll/epoll这个几个IO事件检测API的实现.此处做一些记录.其基本的原理是相同的,流程如下 先依次调用fd对应的struct file.f_op->poll()方法(如果有提供实现的话),尝试检查每个提供待检测IO的fd是否已经有IO事件就绪 如果已经有IO事件就绪,则直接所收集到的IO事件返回,本次调用结束 如果暂时没有IO事件就绪,则根据所给定的超时参数,选择性地进入等待 如果超时参数指示不等待,则

I/O多路复用之select,poll,epoll简介

一.select 1.起源 select最早于1983年出现在4.2BSD中(BSD是早期的UNIX版本的分支). 它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作. 2.select的优点 目前几乎在所有的平台上支持,具有良好的跨平台支持. 3.select的缺点 单个进程能够监视的文件描述符的数量存在最大限制.默认情况下,在Linux上单个进程能够打开的最