Linux 下 Select,epoll对比_select/poll/epoll的区别

epoll 和 select 都是 Linux 下 I/O 多路复用机制(I/O multiplexing) 的实现方式,用来高效监听多个文件描述符(socket、文件等)的 I/O 事件(如可读、可写、异常)。

1. 什么是 select?

select() 是最早期的 I/O 多路复用接口,定义在 <sys/select.h> 中。

特点:

  • 接口:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • 核心机制:用户将要监听的文件描述符集合传入内核,内核遍历每个 fd 的状态,将结果写回到用户空间。
  • 监听 fd 数有限制:1024(默认),可通过 FD_SETSIZE 修改。
  • 每次调用都要复制 fd 集合(开销大)并重新设置监听集合。
  • 内核每次都要 线性遍历 所有 fd(O(n))。

2. 什么是 epoll?

epoll 是 Linux 2.6 内核引入的新接口,解决了 select/poll 的性能问题。

特点:

  • 包括三个系统调用:
    • epoll_create():创建 epoll 实例
    • epoll_ctl():注册、修改、删除监听的 fd
    • epoll_wait():阻塞等待事件发生
  • 不限制监听 fd 的数量(只受系统 ulimit 限制)
  • 内核内部维护事件列表(红黑树 + 就绪队列),避免每次复制大量 fd。
  • 使用回调机制通知事件(高效),无需每次遍历所有 fd(性能 O(1))

3. select 与 epoll 的关系

它们都是 Linux 提供的 I/O 多路复用 API,用于处理高并发连接的网络程序(如 Nginx、Redis、Kafka、Go/Rust 网络库)。

对比项

select

epoll

引入时间

早期 Unix/Linux

Linux 2.6+

fd 数限制

有(默认 1024)

无限制(受 ulimit 限制)

内核数据结构

数组 + 位图

红黑树(管理)+ 链表(事件队列)

性能

O(n)

O(1)(事件触发)

事件通知方式

轮询(每次遍历)

回调(只返回活跃 fd)

是否支持边缘触发

支持 ET(Edge Triggered)

是否跨平台

是(POSIX 标准)

否(Linux 特有)

4. 举例:谁在用 epoll?

  • Nginx:使用 epoll 高效处理成千上万并发连接。
  • Redis:Linux 下优先使用 epoll。
  • libevent、libev、tokio、Go runtime:都会在 Linux 下优先使用 epoll。

5. 总结一句话:

select 是老旧但广泛支持的接口,epoll 是 Linux 下专为高性能而生的多路复用机制,二者本质都是为了解决“一个线程/进程同时监听多个 I/O”的问题。

如果你是做高性能网络编程或系统服务,在 Linux 上应该优先使用 epoll。

原文链接:,转发请注明来源!