【总结笔记】深度理解 Web Server 技术 —— 深入理解 epoll
1 数据结构
epoll 有 2 个重要数据结构:rbtree 与 ready list。epoll 是有状态的,内核维护 eventpoll 数据结构来管理所要监视的 fd。在 eventpoll 中有一棵红黑树,用来快速查找和修改要监视的 fd;还有一个 ready list 用来收集已经发生事件的 epitem。
2 应用场景
epoll 应用,适合海量数据,一个时间段内部分活跃的用户群体。
优点:与 select、poll 相比,epoll 能够解决惊群效应。
引用:例如 app,正常用户并不是 24 小时都拿起手机玩个不停,可能玩一下,又去干别的事,回头又玩一下,断断续续地操作。即便正在使用 app 也不是连续产生读写通信事件,可能手指点击几下页面,页面产生需要的内容,用户就去浏览内容,不再操作了。换句话说,在海量用户里,同一个时间段内,很可能只有一小部分用户正在活跃,而在这一小部分活跃用户里,又只有一小撮人同时点击页面上的操作。那 epoll 管理海量用户,只需要将这一小撮人产生的事件,及时通知 appserver 处理逻辑即可。
3 接口
1)epoll_create:创建 epoll
2)epoll_ctl:fd 事件注册函数,用户通过这个函数关注 fd 读写事件
//将内核事件表注册读事件,ET模式,选择开启EPOLLONESHOT
void addfd(int epollfd, int fd, bool one_shot)
{
epoll_event event;
event.data.fd = fd;
#ifdef connfdET
event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
#endif
#ifdef connfdLT
event.events = EPOLLIN | EPOLLRDHUP;
#endif
#ifdef listenfdET
event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
#endif
#ifdef listenfdLT
event.events = EPOLLIN | EPOLLRDHUP;
#endif
if (one_shot)
event.events |= EPOLLONESHOT;
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
setnonblocking(fd);
}
3)epoll_wait:阻塞等待 fd 事件发生
4 事件
1)EPOLLIN:有可读事件到达;
2)EPOLLOUT:有数据可写;
3)EPOLLERR:文件描述符出错;
4)EPOLLHUP:文件描述符挂断;
5)EPOLLEXCLUSIVE:唯一唤醒事件,解决 epoll_wait 惊群问题。多线程下多个 epoll_wait 同时等待,只唤醒一个 epoll_wait 执行
-
备注:惊群问题
惊群问题是指多进程(多线程)在同时阻塞等待同一个事件的时候,如果该事件发生,则所有阻塞的进程(线程)都会被唤醒,但最终只有一个进程(线程)获得 CPU 控制权,其他进程(线程又得被阻塞),这造成了严重的系统上下文切换代价。
解决办法:使用锁机制。简单来说,当一个连接来的时候,每个进程的 epoll 事件列表都含有该 fd,抢到锁的进程先释放锁,再 accept,没有抢到锁的进程把该 fd 从事件列表移除,不必再调用 accept,造成资源浪费。
6)EPOLLET:边缘触发模式
4 epoll 的初始化 —— slab 算法
这一 小节主要总结 slab 算法
epoll 初始化时,slab 算法为 epoll 分配资源。何为 slab 算法?
slab 是 Linux 的一种内存分配机制。对于一些小内存对象,如进程描述符,如果使用伙伴算法进行分配和释放,不仅会产生大量内存碎片,处理速度也缓慢。slab 分配器就是一个内存池思想。它将相同类型的对象归为一类(如进程描述符就是一类),每当要申请一个这样的对象,就从 slab 列表分配一个单元出去,释放时,又将该单元归回该对象链表中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~