epoll 基础简介
相关函数介绍
epoll_create函数
epoll_create函数用于创建epoll文件描述符,改文件描述符用于后续的epoll操作,参数size目前还没有实际用处
1 2 3 4
| #include <sys/epoll.h>
int epoll_create(int size);
|
epoll_ctl函数
epoll_ctl函数用于增加,删除,修改epoll事件,epoll事件(其实就是fd文件描述符)会存储在内核epoll结构体红黑树中。
1 2 3 4 5 6 7 8 9 10
| #include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 参数: epfd: epoll文件描述符 op: 操作码 -> EPOLL_CTL_ADD:插入事件,EPOLL_CTL_DEL:删除事件,EPOLL_CTL_MOD:修改事件 fd: 事件绑定的套接字文件描述符 event:事件结构体
返回值: 成功 -> 0, 失败 -> -1
|
struct epoll_event结构体
struct eventpoll中有wq-等待队列(存储正在等待IO事件发生的线程),rdlist:就绪队列(双向链表实现)(存储已经就绪的IO事件),rbr:红黑树(存储注册到epoll实例上的文件描述符)
1 2 3 4 5 6 7 8 9
| struct eventpoll { wait_queue_head_t wq; struct list_head rdllist; struct rb_root rbr; ...... }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <sys.epoll.h>
struct epoll_event { uint32_t events; epoll_data_t data; }
typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64; } epoll_data_t;
|
epoll事件列表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <sys/epoll.h>
enum EPOLL_EVENTS { EPOLLIN = 0x001, EPOLLPRI = 0x002, EPOLLOUT = 0x004, EPOLLEDNORM = 0x040, EPOLLRDBAND = 0x080, ... EPOLLERR = 0x008, EPOLLHUP = 0x010, ... EPOLLET = 1u << 31
|
epoll_wait函数
epoll_wait用于监听套接字事件,可以通过设置超时时间timeout来控制监听的行为为阻塞模式还是超时模式
- 若队列非空,立即返回就绪事件
- 若队列为空,进程进入阻塞状态,直到有事件发生或者超时
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <sys/epoll.h>
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
参数: epfd: epoll文件描述符 events: epoll事件数组 maxevents: epoll事件数组长度 timeout: 超时时间 小于0:一直等待 等于0:立即返回 大于0:等待超时时间返回,单位毫秒
|
LT模式和ET模式
LT模式:水平触发
socket都触发:socket接收缓冲区有数据,会一直触发epoll_wait EPOLLIN事件,直到数据被用户读取完
socket写触发:socket可写,会一直触发epoll_wait EPOLLOUT事件
ET模式: 边缘触发
socket读触发:socket数据从无到有,才会触发一次epoll_wait EPOLLIN事件
socket写触发:socket可写,会触发一次epoll_wait EPOLLOUT事件
总结
epoll 通过红黑树管理 fd、回调机制驱动事件通知、就绪队列快速返回有效事件,解决了 select
/poll
的性能瓶颈。其设计核心是 “事件驱动” 和 “高效数据结构”,是 Linux 高并发编程的基石之一。
参考文章
epoll的底层实现原理_epoll底层原理-CSDN博客
linux epoll 机制