`epoll`、`select` 和 `poll` 都是在 Linux 系统中用于实现 I/O 多路复用的机制,它们都能够实现在多个文件描述符上进行非阻塞的 I/O 操作,并在有 I/O 事件发生时通知应用程序。以下是它们的一些比较:
1. **`select`**:
- `select` 是 Unix 系统最早的一种多路复用机制之一。
- 它采用轮询的方式监视一组文件描述符,当其中任何一个文件描述符上有 I/O 事件发生时,就通知应用程序。
- 在 Windows 平台上也有相应的实现,名为 `WSASelect`。
2. **`poll`**:
- `poll` 是 `select` 的改进版本,解决了 `select` 的一些限制。
- 它同样采用轮询的方式监视一组文件描述符,但是不受文件描述符数量的限制,因为内核使用链表来存储监视的文件描述符。
- `poll` 使用 `pollfd` 结构来表示文件描述符及其关注的事件。
3. **`epoll`**:
- `epoll` 是 Linux 特有的一种 I/O 多路复用机制,是 `poll` 的进一步改进。
- 它采用事件驱动的方式,内核会在文件描述符上发生事件时通知应用程序,避免了轮询的开销。
- `epoll` 支持边沿触发(Edge Triggered)和水平触发(Level Triggered)两种模式,可以更精确地控制事件通知。
- `epoll` 使用三个系统调用 `epoll_create`、`epoll_ctl` 和 `epoll_wait` 来实现对事件的操作和等待。
在实际应用中,`epoll` 的性能通常优于 `select` 和 `poll`,尤其在处理大量连接时。因此,在 Linux 下开发网络服务器时,通常会优先选择 `epoll`。
select解决的poll问题:
`select` 解决了 `poll` 的两个主要限制:
1. **文件描述符数量的限制**:
- 在一些早期的 Unix 系统中,`poll` 函数的参数是一个数组,它的大小是固定的,通常是 `FD_SETSIZE`,即能够监视的文件描述符数量是有限的。
- 而 `select` 使用了一种位图的方式,它将所有要监视的文件描述符构成一个位图,可以监视的文件描述符数量理论上是没有限制的(实际上,也会受到系统资源的限制,但比 `poll` 更大)。
2. **效率问题**:
- `poll` 每次调用都要传递一个大的数组,即使只有少数的文件描述符发生了事件,内核也会检查数组中的每一个文件描述符,因此当文件描述符数量很大时,效率可能会比较低下。
- `select` 使用了位图的方式,内核只需要检查被置位的文件描述符,因此在文件描述符数量较大时,效率更高。
总的来说,`select` 解决了 `poll` 中的文件描述符数量限制和效率问题,因此在一些早期的 Unix 系统中,`select` 比 `poll` 更常用。但是在现代的 Linux 系统中,通常会优先选择 `epoll`,因为它更加高效和灵活。
epoll解决的select问题:
在选择使用 `epoll` 而不是 `select` 的原因主要有以下几点:
1. **性能优势**:
- `epoll` 使用了事件驱动的方式,当文件描述符上有事件发生时,内核会立即通知应用程序,而不需要像 `select` 那样需要轮询所有的文件描述符。因此,在处理大量连接时,`epoll` 的性能通常优于 `select`。
2. **支持大量文件描述符**:
- `epoll` 没有像 `select` 那样受到文件描述符数量限制,可以处理更多的文件描述符,因此在高并发环境下更为适用。
3. **支持边沿触发模式**:
- `epoll` 支持边沿触发(Edge Triggered)模式,可以更精确地控制事件的通知,只有当状态变化时才会通知应用程序,而 `select` 和 `poll` 只支持水平触发(Level Triggered)模式。
4. **更少的系统调用**:
- 使用 `epoll` 只需要三个系统调用 `epoll_create`、`epoll_ctl` 和 `epoll_wait`,而 `select` 需要调用 `select` 函数,同时需要维护 `fd_set` 集合,因此 `epoll` 的系统调用次数更少,效率更高。
综上所述,`epoll` 在处理高并发、大量连接的网络应用中表现更为优越,因此在现代的 Linux 系统中,通常会优先选择使用 `epoll`。
标签:文件,epoll,描述符,Linux,poll,select From: https://www.cnblogs.com/whcjob/p/18194533