select poll epoll的区别

I/O多路复⽤通常通过select、poll、epoll等系统调⽤来实现。

同步IO select: select是⼀个最古老的I/O多路复⽤机制,它可以通过轮询的方式监视多个⽂件描述符的可读、可写和错误状态。然而,但是它的效率可能随着监视的⽂件描述符数量的增加⽽降低。

触发方式:水平触发

(单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数量;(在linux内核头文件中定义:#define _FD_SETSIZE 1024)

同步IO poll: poll是select的⼀种改进,它也使⽤轮询⽅式来检查多个⽂件描述符的状态,没有最大文件描述符数量的限制(select使用的是定长数组,而poll是通过链表的形式(pollfd[]))。但对于⼤量的⽂件描述符,poll的性能也可能变得不够高效。

触发方式:水平触发

异步IO epoll: epoll是Linux特有的I/O多路复⽤机制,相较于select和poll,它在处理大量⽂件描述符时更加⾼效。 epoll使⽤事件通知的⽅式,只有在⽂件描述符就绪时才会通知应⽤程序,而不需要应⽤程序轮询。 I/O多路复⽤允许在⼀个线程中处理多个I/O操作,避免了创建多个线程或进程的开销,允许在⼀个线程中处理多个 I/O操作,避免了创建多个线程或进程的开销。

触发方式:水平触发(默认为水平触发) or  边缘触发 

触发模式

  1. 边缘触发(Edge Triggered, ET) 在这种模式下,当一个文件描述符满足特定条件(例如,有可读数据)时,epoll_wait()会返回该文件描述符。然后,应用程序需要立即处理这个事件。如果处理不完全(例如,只读取了一部分数据),那么epoll将不会再次报告该事件,直到下次满足条件时才会报告。优点:这种方式有助于提高系统的效率,因为它减少了epoll调用的次数,因此减少了用户态和内核态的切换。缺点:无法确保一次读取的完全。

  2. 水平触发(Level Triggered, LT) 在这种模式下,每当一个文件描述符满足特定条件时,epoll_wait()都会返回该文件描述符。这意味着,即使应用程序已经处理了某个事件,只要该事件仍然存在,epoll就会持续报告它。优点:这种方式更易于编程,因为程序员不需要担心遗漏任何事件,同时可以确保数据的完整性。缺点:需要频繁进行用户态和内核态的切换。

 区别:

  1. 支持的最大连接数: select只支持最大fd < 1024,如果单个进程的文件句柄数超过1024,select就不能用了。poll在接口上无限制,考虑到每次都要拷贝到内核,一般文件句柄多的情况下建议用epoll;epoll支持更大的连接数,可以在1GB内存的机器上处理大约10万个连接。
  2. I/O效率: 随着连接数的增加,select和poll的I/O效率会出现明显的下降,这是因为它们需要遍历所有连接以确定哪些连接已经准备好进行读写操作。而epoll通过回调机制实现了更高的I/O效率,因为只有那些准备好的连接才会触发回调函数。
  3. 消息传递方式: select和poll需要将消息从用户空间传递到内核空间,并在事件发生时将其返回到用户空间,这涉及到大量的内存拷贝和上下文切换。而epoll 在内核里使用红黑树来跟踪进程所有待检测的文件描述字,把需要监控的 socket 通过 epoll_ctl() 函数加入内核中的红黑树里,红黑树是个高效的数据结构,增删改一般时间复杂度是 O(logn)。而 select/poll 内核里没有类似 epoll 红黑树这种保存所有待检测的 socket 的数据结构,所以 select/poll 每次操作时都传入整个 socket 集合给内核,而 epoll 因为在内核维护了红黑树,可以保存所有待检测的 socket ,所以只需要传入一个待检测的 socket,减少了内核和用户空间大量的数据拷贝和内存分配。第二点, epoll 使用事件驱动的机制,内核里维护了一个链表来记录就绪事件,当某个 socket 有事件发生时,通过回调函数内核会将其加入到这个就绪事件列表中,当用户调用 epoll_wait() 函数时,只会返回有事件发生的文件描述符的个数,不需要像 select/poll 那样轮询扫描整个 socket 集合,大大提高了检测的效率。
  4. select的优点:1、select的可移植性好,因为在某些Unix系统上并不支持poll 和 epoll(极少)。2、select 对于超时时间提供了更好的精度:微秒,而 poll 和 epoll 都是毫秒级。

  5. select的timeout使用的是struct timeval *timeout(需要定义结构体,设置结构体),poll/epoll的timeout单位是int(直接在对于参数位置上给定就好)。select的timeout为NULL时表示无限等待,否则是指定的超时目标时间;poll的timeout为-1表示无限等待。所以有用select来实现usleep的。

注意:

1.epoll建议设置为阻塞的(timeout设置为-1,即一直等待),当epoll_wait未检测到epoll事件时,会出让CPU,阻塞进程,这种阻塞是非常有必要的,如果不及时出让CPU会浪费CPU资源,导致其他任务无法抢占CPU,只要epoll机制能够在检测到epoll事件后,及时唤醒进程处理,并不会影响epoll性能。

2.采用IO复用机制时,socket采用非阻塞方式

select/poll/epoll机制属于IO多路复用机制,这种机制的特点是一个进程处理多路IO请求,如果socket设置成阻塞模式会存在以下几个问题:

  • 一个进程同一时间只能处理一个socket数据,如果socket被阻塞,那么该进程无法处理其他的socket数据,严重影响了性能。
  • 阻塞的本质是进程状态和上下文的切换,频繁的阻塞会把让CPU一直处于上下文切换的状态,导致CPU瞎忙。

更全面的:

一篇文章让你真正搞懂epoll机制 - 知乎 (zhihu.com)的第7小节

图解 | 深入揭秘 epoll 是如何实现 IO 多路复用的! - 知乎 (zhihu.com)

select和poll的区别 - 知乎 (zhihu.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值