epoll详解

1.epoll的工作流程

在学习epoll的ET模式和LT模式之前,先看下epoll的工作流程。epoll最大的好处是不会随着fd数目的增长而降低效率,因为他有一个记录变化的fd的列表,不需要去轮询。
epoll的三个接口函数

  1. int epoll_creat(int size);
    创建一个epoll句柄,size是告诉内核这个监听数目一共多大,当创建好句柄后,他会占用一个fd值,在linux下如果查看/proc/pid/fd,可以看到这个fd,所以在使用完epoll之后,必须调用close()关闭,否则可能会导致fd被耗尽。注:fd是文件描述符,是进程独有的描述文件描述符表的索引,根据这个索引可以找到inode table,进而描述底层文件,fd可以指向套接字、管道等。

在调用epoll_creat()函数后,发生的事情

  • 内核会帮我们在epoll文件系统里创建一个file结点
  • 在内核cache里创建一个红黑树用于储存以后epoll传来的socket
  • 内核建立一个edlist双向链表,用于存储准备就绪的事件
  • 在epoll中的事件会与设备建立回调关系,也就是说相应的事件会调用这里的回调方法,这个回调方法在内核中叫做ep_poll_callback,他会把这样的事件放到上面的rdlist双向链表中
  1. int epoll_ctl(int epfd,int top,int fd,struct epoll_event *event);
    epoll的事件注册函数
    第一个参数是epoll_creat()的返回值。
    第二个参数表示动作,用三个宏来表示
    EPOLL_CTL_ADD:注册新的fd到epfd中;
    EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
    EPOLL_CTL_DEL:从epfd删除一个fd。
    第三个参数是需要监听的fd。
    第四个参数:是告诉内核需要监听什么事,struct epoll_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_data_t data;
    };
    events可以是这几个宏的集合:
    EPOLLIN:表示对应的文件描述符可以读(包括对端socket正常关闭)
    EPOLLOUT:表示对应的文件描述符可以写
    EPOLLPRI:表示对应的文件描述符有紧急的数据可读
    EPOLLERR:表示对应的文件描述符发生错误
    EPOLLHUP:表示对应的文件描述符挂断
    EPOLLET:将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平出发(Level Triered)来说的
    EPOLLIONSHOTl只监听一次事件,当监听完这次事件之后,如果还要继续监听这个socket,需要再次把这个socket加入到EPOLL队列里。
  2. int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
    等待事件的产生,类似于select的调用,参数events用来从内核得到事件的集合,maxevents告之这个events有多大,这个maxevents的值不能大于创建epoll_creat()的size,参数timeout是超时时间(毫秒,0会立即返回,-1是不确定,有的说是永久阻塞)。该函数返回需要处理的时间数目,如返回0表示已经超时。

2.ET和LT

  • LT(水平触发)模式下,只要这个文件描述符还有数据可读,每次 epoll_wait都会返回它的事件,提醒用户程序去操作;

  • ET(边缘触发)模式下,在它检测到有 I/O 事件时,通过 epoll_wait 调用会得到有事件通知的文件描述符,对于每一个被通知的文件描述符,如可读,则必须将该文件描述符一直读到空,让 errno 返回 EAGAIN 为止,否则下次的 epoll_wait 不会返回余下的数据,会丢掉事件。如果ET模式不是非阻塞的,那这个一直读或一直写势必会在最后一次阻塞。
    -在这里插入图片描述

  • 采取ET的好处:
    如果采用EPOLLLT模式的话,系统中一旦有大量你不需要读写的就绪文件描述符,它们每次调用epoll_wait都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率.。而采用EPOLLET这种边缘触发模式的话,当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符。

3.反应堆模型


参考文献1 https://blog.csdn.net/dorevers/article/details/82081672
参考文献2 https://blog.csdn.net/daaikuaichuan/article/details/83862311

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值