首页 > 试题广场 >

请你说一说epoll原理

[问答题]

请你说一说epoll原理

推荐

得分点

epoll_create、epoll_ctrl、epoll_wait、红黑树、双向链表、epoll的两种工作模式

参考答案

标准回答

epoll 是一种更加高效的 IO 复用技术,epoll 的使用步骤及原理如下:

  1. 调用 epoll_create() 会在内核中创建一个 eventpoll 结构体数据,称之为 epoll 对象,在这个结构体中有 2 个比较重要的数据成员,一个是需要检测的文件描述符的信息 struct_root rbr(红黑树),还有一个是就绪列表struct list_head rdlist,存放检测到数据发送改变的文件描述符信息(双向链表);
  2. 调用 epoll_ctrl() 可以向 epoll 对象中添加、删除、修改要监听的文件描述符及事件;
  3. 调用 epoll_wait() 可以让内核去检测就绪的事件,并将就绪的事件放到就绪列表中并返回,通过返回的事件数组做进一步的事件处理。

epoll 的两种工作模式:

  1. LT 模式(水平触发)

    LT(Level - Triggered)是缺省的工作方式,并且同时支持 Block 和 Nonblock Socket。在这种做法中,内核检测到一个文件描述符就绪了,然后可以对这个就绪的 fd 进行 IO 操作,如果不作任何操作,内核还是会继续通知。

  2. ET 模式(边沿触发)

    ET(Edge - Triggered)是高速工作方式,只支持 Nonblock socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过 epoll 检测到。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了。但是请注意,如果一直不对这个 fd 进行 IO 操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)。

    ET 模式在很大程度上减少了 epoll 事件被重复触发的次数,因此效率要比 LT 模式高。epoll 工作在 ET 模式的时候,必须使用非阻塞套接口,以避免由于一个文件描述符的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。

延伸阅读

epoll 相关 api:

#include <sys/epoll.h>

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);    
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

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;
编辑于 2021-09-15 14:16:25 回复(0)
epoll是IO多路复用技术,在实现上维护了一个用于返回触发事件的Socket的链表和一个记录监听事件的红黑树
epoll的高效体现在:
1)对监听事件的修改是 log N(红黑树)
2)用户程序无需遍历所有的Socket(发生事件的Socket被放到链表中直接返回)
3)内核无需遍历所有的套接字,内核使用回调函数在事件发生时直接转到对应的处理函数
发表于 2023-08-02 18:17:21 回复(0)
通过epoll_create生成一个存储结构称之为epoll对象, 主要包含两个属性, 其一是用来保存当前待检测文件描述符的红黑树, 其二是检测到状态发生变化的文件描述符的双向链表.
通过epoll_ctrl函数可以向epoll对象中插入, 修改, 删除待检测的文件描述符.
通过epoll_wt可以让系统自动监控文件描述符的状态, 将需要发生IO操作的文件描述符整合到一起, 通过返回的文件描述符数组做进一步事件处理.
具体的操作原理有两种方式: 水平触发 与 边沿触发
其中水平触发为缺省的工作模式, 分为阻塞与非阻塞两种工作方式, 当检测到文件描述符状态发生改变时, 系统会直接发送一个通知, 即使没有做任何IO操作, 系统还是会继续通知.
边沿触发是另一种高效的工作模式, 只要非阻塞的工作方式, 当检测到文件描述符状态发生改变时, 系统会假定已经知道文件描述符发生改变, 并且不会继续发送更多的通知, 除非人为操作了IO操作使该文件描述符的状态发生改变, 否则系统仅通知一次, 避免了水平工作模式下的多次重复通知而浪费系统资源, 性能更加优异, 但只能采用非阻塞的工作方式.
发表于 2023-02-12 13:04:02 回复(0)