select/poll/epoll

文章目录

  • select/poll
  • epoll


select/poll

select 实现多路复⽤的⽅式是,将已连接的 Socket 都放到⼀个⽂件描述符集合,然后调⽤select 函数将⽂件描述符集合拷⻉到内核⾥,通过遍历⽂件描述符集合的⽅式,当检查到有事件产⽣后,将此 Socket 标记为可读或可写, 接着再把整个⽂件描述符集合拷⻉回⽤户态⾥,然后⽤户态还需要再通过遍历的⽅法找到可读或可写的 Socket,然后再对其处理。

需要进⾏ 2 次「遍历」⽂件描述符集合,⼀次是在内核态⾥,⼀个次是在⽤户态⾥ ,⽽且还会发⽣ 2 次「拷⻉」⽂件描述符集合,先从⽤户空间传⼊内核空间,由内核修改后,再传出到⽤户空间中。

所⽀持的⽂件描述符的个数是有限制的,在 Linux 系统中,由内核中的 FD_SETSIZE 限制, 默认最⼤值为 1024

poll 和 select 并没有太⼤的本质区别,都是存储进程关注的 Socket集合,因此都需要遍历⽂件描述符集合来找到可读或可写的 Socket,⽽且也需要在⽤户态与内核态之间拷⻉⽂件描述符集合,这种⽅式随着并发数上来,性能的损耗会呈指数级增⻓。

很明显发现,select 和 poll 的缺陷在于,当客户端越多,也就是 Socket 集合越⼤,Socket集合的遍历和拷⻉会带来很⼤的开销,因此也很难应对 C10K。

epoll

epoll 通过两个⽅⾯,很好解决了 select/poll 的问题。

第⼀点,epoll 在内核⾥使⽤红⿊树来跟踪进程所有待检测的⽂件描述字,这样就不需要像 select/poll 每次操作时都传⼊整个 socket 集合,只需要传⼊⼀个待检测的 socket,减少了内核和⽤户空间⼤量的数据拷⻉和内存分配。

第⼆点, epoll 使⽤事件驱动的机制,内核⾥维护了⼀个链表来记录就绪事件,只会返回有事件发⽣的⽂件描述符的个数,不需要像 select/poll 那样轮询扫描整个 socket 集合,⼤⼤提⾼了检测的效率。

epoll 的⽅式即使监听的 Socket 数量越多的时候,效率不会⼤幅度降低,能够同时监听的Socket 的数⽬也⾮常的多了,上限就为系统定义的进程打开的最⼤⽂件描述符个数。因⽽,epoll 被称为解决 C10K 问题的利器。

你可能感兴趣的:(操作系统,网络,bio,epoll)