zoukankan      html  css  js  c++  java
  • epoll相关

    IO事件通知机制。

    1. 简介

    poll(2)类似,可以同时监测多个文件描述符上的事件。可以使用水平触发和边沿触发两种模式,可以同时监听大量fd,而且性能很好。

    • epoll_create(2)创建一个epoll实例,并返回一个fd用于控制该实例。
    • epoll_ctl(2)添加感兴趣的fd到epoll中
    • epoll_wait(2)等待IO事件发生

    1.1. 水平触发(LT)和边沿触发(ET)

    加入epoll监听fd集中的fd可以采用LT和ET通知模式,在读事件发生时,如果没有一次性读完所有数据,采用LT的fd下次还将通过epoll触发读事件,而采用ET的fd下次不会再触发读事件。也就是说,如果使用ET,程序需要在一次读事件通知时,把系统缓存中的数据全部读出,否则剩下的数据很可能会一直留在系统缓存,而没有事件来通知。

    因此使用ET时,需要注意两点:

    • 使用非阻塞的fd
    • read(2)write(2)返回EAGAIN时,才使用epoll等待事件,否则可以一直无阻塞的进行读写事件。

    如果使用LT,就跟poll(2)的语义基本一样了。

    使用ET也可能因为多次收到数据,而产生多个事件,这样在处理该fd上的第一个事件时,下次循环还可能触发第二次事件,但因为第一次已经读完的数据,所以第二次可能就没数据可以读了。用户可以使用EPOLLONESHOT标记告诉epoll触发一次事件后,将fd从监听集中移除,但这样需要用户下次使用的时候,自己加进去。

    1.2. /proc接口

    /proc/sys/fs/epoll/max_user_watches规定了当前用户可以通过1个epoll实例注册监听的最大fd个数。每个注册的fd在32位内核上消耗大概90字节,64位上消耗大概160字节。默认个数是可用最小内存的1/25除以消耗的字节数。

    2. 基本用法

    2.1. 创建epoll

    #include <sys/epoll.h>
    
    int epoll_create(int size); // size被忽略,但必须大于0
    int epoll_create1(int flags);
    

    如果flags为0,两个函数一样。flags可以为EPOLL_CLOEXEC,多线程中有用,一个线程创建epoll,另一个线程执行fork+execv,会出现竞争,使用这个flag可以避免竞争。

    2.2。 操作监听fd集

    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 */
    };
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
    

    op可以是:

    • EPOLL_CTL_ADD: 注册监听fd
    • EPOLL_CTL_MOD: 修改监听fd的事件
    • EPOLL_CTL_DEL: 删除监听的fd

    events可以是:

    • EPOLLIN: fd可读
    • EPOLLOUT:fd可写
    • EPOLLRDHUP:流式socket对端关闭或对端写关闭。
    • EPOLLPRI: read(2)读取带外数据
    • EPOLLERR: fd上有错误发生,epoll会一直监听该事件,不用手动设置
    • EPOLLHUP: fd挂起,epoll会一直监听该事件,不用手动设置
    • EPOLLET: 设置ET模式,默认是LT
    • EPOLLONESHOT:fd只触发一次事件,下次需要重新注册

    2.3. 等待事件

    // timeout单位是ms
    int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
    int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask);
    

    这两个的区别跟select(2)pselect(2)的一样。

  • 相关阅读:
    PHP识别二维码功能,php-zbarcode 安装
    《架构即未来》读后感(三)
    MVC设计模式案例分析
    SOA
    《架构即未来》读后感(二)
    基于网络拓扑及告警的故障根因定位系统实现及算法研究赛题需求分析
    《架构即未来》读后感(一)
    《大型网站技术架构》读后感(二)
    《一线架构师实践指南》读后感(三)
    《大型网站技术架构》读后感(三)
  • 原文地址:https://www.cnblogs.com/suntus/p/14909369.html
Copyright © 2011-2022 走看看