epoll 是什么
epoll 是一个高性能的 I/O 事件通知机制,它是 Linux 内核提供的一种 I/O 多路复用方式。与其他传统的 I/O 多路复用机制如 select 和 poll 相比,epoll 具有更高的扩展性和效率。
使用 epoll,应用程序可以监控多个文件描述符上的 I/O 事件,包括读、写、错误、优先级等事件。当任何一个事件发生时,epoll 会通知应用程序,并返回相关的文件描述符,从而让应用程序可以立即处理这些事件。
相比于传统的 I/O 多路复用方式,epoll 具有以下优势:
没有最大并发连接的限制,适用于高并发网络程序;
可以更快地检索和响应大量的事件;
采用事件驱动方式,减少了系统调用次数,从而提高了效率;
支持边缘触发和水平触发两种模式,更加灵活。
epoll实现原理
1.内核开辟一个事件表(event table)来存储被监控的文件描述符及其状态信息。
2.epoll_create 系统调用会创建一个 epoll 对象,并返回一个文件描述符(epoll fd),用于后续的操作。
3.使用 epoll_ctl 系统调用向 epoll 中添加、修改或删除需要监控的文件描述符。每个文件描述符都对应着一个 epoll_event 结构体,其中包含了该文件描述符需要监控的事件类型(读、写、错误等)以及事件发生后的回调函数(callback function)。
4.当某个文件描述符上的事件发生时,内核会将事件信息添加到事件表中,并将 epoll 对象对应的等待队列(waiting queue)中的进程唤醒。
5.应用程序可以使用 epoll_wait 系统调用来阻塞等待事件的发生。当事件发生时,epoll_wait 会返回事件信息及相关的文件描述符,应用程序可以在回调函数中处理这些事件。
6.当不再需要监控某个文件描述符时,可以使用 epoll_ctl 系统调用将其从 epoll 中删除。
epoll 实现源码
1.epoll_ctl 函数用于向 epoll 实例注册、修改或删除一个事件。
SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event)
{
struct eventpoll *ep = NULL;
struct file *file;
struct epoll_event epds;
int error = -EINVAL;
...
/* 获取 epoll 实例和文件对象 */
error = -EBADF;
file = fget(epfd);
if (!file