前情提要:
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
《redis 从0到1完整学习 (七):ZipList 数据结构》
《redis 从0到1完整学习 (八):QuickList 数据结构》
《redis 从0到1完整学习 (九):SkipList 数据结构》
《redis 从0到1完整学习 (十):RedisObject 数据结构》
《redis 从0到1完整学习 (十一):RedisObject 之 String 类型》
《redis 从0到1完整学习 (十二):RedisObject 之 List 类型》
《redis 从0到1完整学习 (十三):RedisObject 之 Set 类型》
《redis 从0到1完整学习 (十四):RedisObject 之 ZSet 类型》
《redis 从0到1完整学习 (十五):RedisObject 之 Hash 类型》
《redis 从0到1完整学习 (十六):内存回收之 key 过期处理策略》
《redis 从0到1完整学习 (十七):内存回收之内存淘汰策略》
《redis 从0到1完整学习 (十八):阻塞/非阻塞 IO》
《redis 从0到1完整学习 (十九):IO多路复用之select和poll》
之前介绍了阻塞、非阻塞 I/O 以及 IO 多路复用机制的 select 和 poll 的机制,本文主要介绍 epoll 的主要流程和原理。
Redis 源码可以点击这里下载,方便查看其中定义的一些数据结构。
回顾上节的 IO 多路复用模型:
在 IO 多路复用机制下,当没有 IO 事件发生时,调用会阻塞进程等待,直到至少有一个文件描述符准备好进行读写操作为止。一旦某个文件描述符就绪(例如有数据可读或可写),系统会立即通知应用程序,并返回所有准备好的文件描述符列表,然后应用程序就可以针对性地对这些已就绪的文件描述符进行相应的读取或写入操作。
下面看下 epoll 的实现原理。
epoll 是 Linux 内核提供的一种高效的 I/O 多路复用机制,它是 select 和 poll 的增强版,在处理大量并发连接时表现更优。epoll 通过解决传统多路复用方法的性能瓶颈来提高服务器端应用程序处理高并发连接的能力。
下面结合 epoll 的整体流程在介绍
图片参考:https://www.processon.com/view/5e8524f3e4b0a2d87028133b
epoll 使用一个内核级别的数据结构(通常是红黑树)来存储待监控的文件描述符集合,而不是每次调用都复制整个集合到内核空间。
(1)应用程序通过 epoll_create
创建一个 epoll 实例(返回一个文件描述符)
int epoll_create(int size);
(2)使用 epoll_ctl
函数向 epoll 实例中添加、修改或删除要监听的文件描述符及其事件类型
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
(3)事件类型如 EPOLLIN、EPOLLOUT 等,具体数据结构如下:
// epoll.h
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
} __EPOLL_PACKED;
事件类型如下:
events | 描述 |
---|---|
EPOLLIN | 可读 |
EPOLLOUT | 可写 |
EPOLLERR | 该文件描述符发生错误 |
EPOLLHUP | 该文件描述符被挂断 |
当任何一个被监视的文件描述符上有事件发生时,内核会将其标记为就绪,并将就绪的描述符数量更新到 epoll 实例上。
应用程序通过调用 epoll_wait
来等待并获取已就绪的文件描述符列表,该函数仅返回实际就绪的描述符,避免了无谓的遍历。
int epoll_wait(int epfd, struct epoll_event* events, int maxevents. int timeout);
其中,事件通知的模式有两种:
epoll_wait
都会返回这个描述符。epoll_wait
获得就绪的文件描述符时,可以通过内存映射技术减少系统调用过程中的数据复制开销,进一步提升效率。总结来说,epoll 提供了一种更加强大且高效的 I/O 事件通知机制,它非常适合构建高性能网络服务器,尤其是在处理大规模并发连接时,可以有效降低上下文切换以及资源占用,从而达到更高的吞吐量和更低的延迟。
《redis 从0到1完整学习 (一):安装&初识 redis》
《redis 从0到1完整学习 (二):redis 常用命令》
《redis 从0到1完整学习 (三):redis 数据结构》
《redis 从0到1完整学习 (四):字符串 SDS 数据结构》
《redis 从0到1完整学习 (五):集合 IntSet 数据结构》
《redis 从0到1完整学习 (六):Hash 表数据结构》
《redis 从0到1完整学习 (七):ZipList 数据结构》
《redis 从0到1完整学习 (八):QuickList 数据结构》
《redis 从0到1完整学习 (九):SkipList 数据结构》
《redis 从0到1完整学习 (十):RedisObject 数据结构》
《redis 从0到1完整学习 (十一):RedisObject 之 String 类型》
《redis 从0到1完整学习 (十二):RedisObject 之 List 类型》
《redis 从0到1完整学习 (十三):RedisObject 之 Set 类型》
《redis 从0到1完整学习 (十四):RedisObject 之 ZSet 类型》
《redis 从0到1完整学习 (十五):RedisObject 之 Hash 类型》
《redis 从0到1完整学习 (十六):内存回收之 key 过期处理策略》
《redis 从0到1完整学习 (十七):内存回收之内存淘汰策略》
《redis 从0到1完整学习 (十八):阻塞/非阻塞 IO》
《redis 从0到1完整学习 (十九):IO多路复用之select和poll》
欢迎关注本人,我是喜欢搞事的程序猿; 一起进步,一起学习;
也欢迎关注我的wx公众号:一个比特定乾坤