epoll

头文件

#include <sys/epoll.h>

epoll概念

epoll是Linux特有的I/O复用函数。它在实现和使用上与select、poll有很大差异。epoll使用一组函数完成任务而非单个函数。epoll把用户关心的文件描述符上的事件放在内核中的一个事件表中,无须像select和poll那样每次调用都要重复传入文件描述符或事件集。但epoll需使用一个额外的文件描述符,来标识内核中的这个时间表。

使用情况:
epoll每次添加文件描述符的时候都需要执行一个系统调用。系统调用的开销是很大的,而且在有很多短期活跃连接的情况下,由于这些大量的系统调用开销,epoll可能会慢于select和poll。

select使用线性表描述文件描述符集合,文件描述符有上限;poll使用链表来描述;epoll底层通过红黑树来描述,并且维护一个ready list,将事件表中已经就绪的事件添加到这里,在使用epoll_wait调用时,仅观察这个list中有没有数据即可。

select和poll的最大开销来自内核判断是否有文件描述符就绪这一过程:每次执行select或poll调用时,它们会采用遍历的方式,遍历整个文件描述符集合去判断各个文件描述符是否有活动;epoll则不需要去以这种方式检查,当有活动产生时,会自动触发epoll回调函数通知epoll文件描述符,然后内核将这些就绪的文件描述符放到之前提到的ready list中等待epoll_wait调用后被处理。

select和poll都只能工作在相对低效的LT模式下,而epoll同时支持LT和ET模式。

综上,当监测的fd数量较小,且各个fd都很活跃的情况下,建议使用select和poll;当监听的fd数量较多,且单位时间仅部分fd活跃的情况下,使用epoll会明显提升性能。

epoll_create

该函数生成一个epoll专用的文件描述符,用来存放你想关注的文件描述符,监视其是否发生以及发生了什么事件。


@param size:现在不起作用,只是给内核一个提示,告诉它事件表需要多大。
int epoll_create(int size)
//返回生成的文件描述符,指示要访问的内核事件表

epoll_ctl

用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。

@param epfd:作用的目标epoll文件描述符
@param op:操作类型
@param fd:需要监听的文件描述符
@param event:需要监听的事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

    event:
        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 */
        };
fd值功能
EPOLL_CTL_ADD往事件表中注册fd上的事件
EPOLL_CTL_MOD修改fd上的注册事件
EPOLL_CTL_DEL删除fd上的注册事件
events值功能
EPOLLIN触发该事件,表示对应的文件描述符上有可读数据。(包括对端SOCKET正常关闭)
EPOLLOUT触发该事件,表示对应的文件描述符上可以写数据
EPOLLPRI表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来)
EPOLLERR表示对应的文件描述符发生错误
EPOLLHUP表示对应的文件描述符被挂断
EPOLLET将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的
EPOLLONESHOT只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

epoll_wait

等待事件的产生,超过timeout时间还没事件发生,则超时

@param epfd:        epoll文件描述符
@param events:      检测到就绪事件就从内核事件表中复制到此数组
@param maxevents:   指定最多监听多少个事件
@param timeout:     指定超时值,单位毫秒。为-1:epoll调用一直阻塞,直到某事件发生;为0:epoll调用立刻返回
int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
//成功时返回就绪的文件描述符的个数,失败返回-1并设置errno

ET与LT模式

ET:events值取EPOLLONESHOT.
LT:events值取EPOLLET.

LT(电平触发):类似select,LT会去遍历在epoll事件表中每个文件描述符,来观察是否有我们感兴趣的事件发生,如果有(触发了该文件描述符上的回调函数),epoll_wait就会以非阻塞的方式返回。若该epoll事件没有被处理完(没有返回EWOULDBLOCK),该事件还会被后续的epoll_wait再次触发。

ET(边缘触发):ET在发现有我们感兴趣的事件发生后,立即返回,并且sleep这一事件的epoll_wait,不管该事件有没有结束。

在使用ET模式时,必须要保证该文件描述符是非阻塞的(确保在没有数据可读时,该文件描述符不会一直阻塞);并且每次调用read和write的时候都必须等到它们返回EWOULDBLOCK(确保所有数据都已读完或写完)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值