Skip to content

epoll ​

epoll 但不止 epoll

select ​

Linux SELECT 是一个系统调用,它可以让程序同时监控多个文件描述符,并等待其中任意一个可用于读、写或异常操作。这种机制可以让程序在多个文件之间高效切换,并有效地利用 CPU 时间。

SELECT 系统调用的一般形式如下:

cpp
int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

它接受五个参数:

  1. nfds 是要监控的文件描述符的最大值加 1。
  2. readfds 是一个指向可读文件描述符集合的指针,在监控期间,如果任意一个描述符可读,SELECT 就会返回。
  3. writefds 是一个指向可写文件描述符集合的指针,在监控期间,如果任意一个描述符可写,SELECT 就会返回。
  4. exceptfds 是一个指向异常文件描述符集合的指针,在监控期间,如果任意一个描述符有异常,SELECT 就会返回。
  5. timeout 是一个指向 timeval 结构的指针,用于指定 SELECT 的超时时间。

SELECT 返回值是可用文件描述符的数量。如果在超时时间内没有可用文件描述符,它会返回 0。如果出错,它会返回 -1。

常用用法 ​

简单的聊天室 ​

使用 SELECT 来实现一个简单的聊天室,它能够同时与多个客户端进行交互。在这个例子中,你可以将 readfds 设置为所有客户端的文件描述符集合,然后在超时时间内不断调用 SELECT,如果发现有客户端发送了消息,就从对应的文件描述符中读取消息并转发给其他客户端。

另外,你也可以使用 SELECT 实现一个多任务的 Web 服务器,它能够同时处理多个客户端的请求。在这个例子中,你可以将 readfds 设置为监听套接字的文件描述符集合,然后在超时时间内不断调用 SELECT,如果发现有新的客户端连接,就接受连接并处理客户端的请求。

总之,Linux SELECT 是一个非常有用的系统调用,它能够帮助程序员实现高效的多任务处理。

实现多任务处理 ​

你可以使用 SELECT 实现一个多线程服务器,它能够同时处理多个客户端的请求。在这个例子中,你可以将 readfds 设置为监听套接字的文件描述符集合,然后在超时时间内不断调用 SELECT,如果发现有新的客户端连接,就接受连接并在新的线程中处理客户端的请求。

另外,你也可以使用 SELECT 实现一个多进程服务器,它能够通过多个进程同时处理多个客户端的请求。在这个例子中,你可以将 readfds 设置为监听套接字的文件描述符集合,然后在超时时间内不断调用 SELECT,如果发现有新的客户端连接,就接受连接并在新的进程中处理客户端的请求。

总之,SELECT 可以作为一种高效的多任务处理方式,它能够帮助你在 Linux 系统中实现高性能的服务器应用程序。

技术细节和注意事项 ​

例如,在调用 SELECT 时,你需要清空文件描述符集合,然后再添加需要监控的文件描述符。这样做的原因是,SELECT 会修改文件描述符集合,并在返回时将可用文件描述符添加到集合中。如果你没有清空集合,那么 SELECT 可能会返回之前添加的无效文件描述符。

另外,在调用 SELECT 时,你还需要注意文件描述符集合的大小。它的大小应该是 nfds 的值加 1,否则 SELECT 可能会出错。例如,如果 nfds 的值为 5,那么文件描述符集合的大小应该是 6,因为它从 0 开始编号。

总之,在使用 SELECT 时,你需要注意文件描述符集合的清空和大小,这样可以避免一些常见的错误。

SELECT 和其他系统调用的区别 ​

SELECT 和其他系统调用的区别在于它们的实现方式和性能。SELECT 是 Linux 内核中最常用的系统调用之一,它能够实现多文件监控和高效的多任务处理。

首先,SELECT 的实现方式与其他系统调用不同。它使用位图来表示文件描述符集合,因此它能够处理较大的文件描述符集合。而其他系统调用,例如 POLL 和 EPOLL,则使用数组来表示文件描述符集合,因此它们能够处理更多的文件描述符,但是对于大的文件描述符集合,它们的性能可能会下降。

其次,SELECT 的性能也与其他系统调用不同。在处理大量的文件描述符时,SELECT 的性能会比 POLL 和 EPOLL 差。这是因为 SELECT 需要在内核空间和用户空间之间进行多次数据拷贝,这会带来额外的开销。而 POLL 和 EPOLL 只需要在内核空间和用户空间之间进行一次数据拷贝,因此它们的性能会更优。

此外,SELECT 还有一些限制,它不能处理超过 1024 个文件描述符。如果需要处理更多的文件描述符,就需要使用其他系统

除了 SELECT,Linux 还提供了其他系统调用来实现多文件监控和多任务处理。例如,POLL 和 EPOLL 都是用于实现多文件监控的系统调用,它们的实现方式和性能都优于 SELECT。

POLL 是 SELECT 的一个改进版本,它使用数组来表示文件描述符集合,因此能够处理更多的文件描述符。它的实现方式比 SELECT 简单,性能也更优。但是它也有一些限制,它不能处理超过 4096 个文件描述符。

EPOLL 是 POLL 的一个改进版本,它的实现方式和性能都比 POLL 更优。它使用哈希表来维护文件描述符集合,因此能够处理更多的文件描述符,并且在处理大量的文件描述符时,它的性能表现更优。

总之,SELECT、POLL 和 EPOLL 都是用于实现多文件监控和高效的多任务处理的系统调用,它们的实现方式和性能

除了 SELECT、POLL 和 EPOLL,Linux 还提供了其他系统调用来实现多文件监控和多任务处理。例如,KQUEUE 和 IO_URING 都是 Linux 专有的系统调用,它们能够提供更加高效和先进的多文件监控功能。

KQUEUE 是一种基于事件驱动的系统调用,它能够支持多种不同类型的事件,包括文件描述符事件、信号事件和定时事件等。它的实现方式比 SELECT、POLL 和 EPOLL 更加复杂,但是它的性能也更优,特别是在处理大量的事件时。

IO_URING 是 Linux 5.1 版本中引入的新系统调用,它提供了一种全新的方式来实现多文件监控和高效的多任务处理。它使用了一种称为“提交队列”的机制来解决 SELECT、POLL 和 EPOLL 的瓶颈,并且能够支持更多的文件描述符和更多类型的事件。它的实现方式和性能都优于其他系统调用,是目前 Linux 系统中最先进的多

poll ​

它可以让程序在多个文件句柄上等待事件的发生。它的作用类似于 select 函数,但是 poll 函数通常更快,并且可以处理更多的文件句柄。

poll 函数通过一个数组来监视多个文件句柄,每个文件句柄都有一个相应的结构体来存储关于它的信息。程序可以通过调用 poll 函数来监测文件句柄上是否有事件发生,例如是否有数据可读或可写。如果有事件发生,poll 函数就会返回一个非零值,并且会更新相应的结构体来表示事件的类型。程序可以通过检查这些信息来处理事件。

使用 poll 函数的好处在于它可以让程序同时监测多个文件句柄,而不需要对每个文件句柄进行单独的处理。这样可以提高程序的效率,并且可以更方便地处理多个文件句柄上的事件。

epoll ​

Linux 的 epoll 是一种高效的 I/O 多路复用技术。它允许程序监控多个文件描述符(file descriptor),当这些文件描述符就绪时,epoll 会通知程序进行相应的读写操作。这样就可以避免程序在等待某个文件描述符就绪时长时间地占用 CPU,提高了程序的效率。

epoll 的工作方式与其它 I/O 多路复用技术,如 select 和 poll 类似。首先,程序将要监控的文件描述符添加到 epoll 实例中,然后调用 epoll_wait 等待文件描述符就绪。当 epoll_wait 返回时,它会将就绪的文件描述符以数组的形式返回,程序再根据文件描述符的就绪状态进行相应的读写操作。

不同之处在于,select 和 poll 的实现方式略有不同,select 具有更高的效率,但它的监控文件描述符的数量受限,而 poll 的效率较低,但可以监控更多的文件描述符。

与 select 和 poll 相比,epoll 具有更高的效率。它的内部实现与内核交互的方式更加高效,并且 epoll 可以监控的文件描述符数量不受限制,因此能够处理大量文件描述符的情况。

总之,epoll 是一种在 Linux 系统中用于提高程序效率的 I/O 多路复用技术,它可以帮助程序在处理大量的文件描述符时获得更好的性能。相比 select 和 poll,epoll 的效率更高,并且可以监控的文件描述符数量没有限制。

如果你想使用 epoll,首先你需要调用 epoll_create 函数来创建一个 epoll 实例。接着,你可以通过调用 epoll_ctl 把需要监控的文件描述符添加到 epoll 实例中。在这之后,你可以调用 epoll_wait 等待文件描述符就绪。当 epoll_wait 返回时,它会返回就绪的文件描述符数组,你可以根据文件描述符的就绪状态进行相应的读写操作。

总的来说,使用 epoll 的流程如下:

  1. 调用 epoll_create 创建一个 epoll 实例。
  2. 调用 epoll_ctl 把要监控的文件描述符添加到 epoll 实例中。
  3. 调用 epoll_wait 等待文件描述符就绪。
  4. 当 epoll_wait 返回时,处理就绪的文件描述符。

通过使用 epoll,你的程序可以在处理大量文件描述符时获得更好的效率。它是在 Linux 系统中常用的 I/O 多路复用技术,值得你去了解和使用。

吃好喝好 快乐地活下去