zoukankan      html  css  js  c++  java
  • epoll 基本知识与使用

    https://blog.csdn.net/qq_35721743/article/details/86742508

    epoll 最大的好处在于它不会随着监听 fd 数目的增长而降低效率。

    epoll 的接口,一共有三个函数, 都在头文件 #include <sys/epoll.h> 里。

    1. 创建 epoll 句柄

      int epfd = epoll_create(intsize);

    创建一个 epoll 句柄,size 用来告诉内核这个监听的数目一共有多大。当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看 /proc/进程id/fd/, 是能够看到这个fd的,所以在使用完epoll后,必须调用 close() 关闭。 否则可能导致 fd 被耗尽。

    函数声明: int epoll_create(int size)

    该函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd 上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd 数, 由用户确定, 只要内存空间够用。

    2. 将被监听的描述符添加到epoll句柄或从epoll句柄中删除或者对监听事件进行修改

    函数声明:int epoll_ctl( int epfd, int op, int fd, struct epoll_event* event )

    返回值:如果调用成功返回0,不成功返回-1.

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

    参数:

    epfd : 由 epoll_create 生成的 epoll 专用的文件描述符;

    op : 要进行的操作,例如注册事件。可能的取值有:

                                EPOLL_CTL_ADD  :  注册新的 fd 到 epfd 中

                                EPOLL_CTL_MOD : 修改已经注册的 fd 的监听事件

                                EPOLL_CTL_DEL : 从 epfd 中删除一个 fd

    fd : 关联的文件描述符,需要监听的 fd .

    event : 指向 epoll_event 的指针, 告诉内核需要监听什么事件 , struct epoll event 结构如下:

    struct epoll_event{
        __uint32_t events; // Epoll events: EPOLLIN,EPOLLOUT,EPOLLPRI,EPOLLERR,EPOLLHUP,EPOLLET,EPOLLONESHOT
        epoll_data_t data;  // User data variable
    };
    
    typedef union epoll_data{
        void *ptr;
        int fd;
        __uint32_t u32;
        __uint64_t u64;
    } epoll_data_t;

    events 可以是一下几个宏的集合:

    EPOLLIN : 触发该事件,表示对应的文件描述符上有可读数据。 (包括对端 SOCKET 正常关闭)

    EPOLLOUT : 触发该事件,表示对应的文件描述符上可以写数据;

    EPOLLPRI : 表示对应的文件描述符上有紧急的数据可读(这里应该表示有带外数据到来);

    EPOLLERR : 表示对应的文件描述符发生错误;

    EPOLLHUP : 表示对应的文件描述符被挂断;

    EPOLLET : 将 EPOLL 设为 边缘触发 (Edge Triggered) 模式,这是相对于水平触发(Level Triggered)来说的。

    EPOLLONESHOT : 只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里。

    如:

    struct epoll_event ev;
    ev.data.fd = listenfd; // 设置与要处理的事件相关的文件描述符
    ev.events = EPOLLIN | EPOLLOUT; // 设置要处理的事件类型
    epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev); // 注册 epoll 事件

    3. 等待事件触发, 当超过 timeout 还没有事件触发时,就超时

    int epoll_wait(  int epfd,   struct epoll_event * events,   int maxevents,   int timeout  );

    返回:该函数返回需要处理的事件数目,返回的事件集合在events数组中,数组中实际存放的成员个数是函数的返回值。如返回0表示已超时。

    参数:

    epfd : 由 epoll_create 生成的epoll专用的文件描述符;

    events : 用于回传待处理的事件的数组,从内核得到事件的集合

    maxevents : 每次能处理的事件数, 告知内核这个events有多大(数组成员的个数),这个maxevents 的值不能大于创建epoll_create()时候的size。

    timeout : 等待 IO 事件发生的超时值; -1相当于阻塞, 0相当于非阻塞

    epoll_wait 运行的原理是: 等待注册在 epfd 上的 socket fd 的 事件发生,如果发生,则将发生的fd 和事件保存在 events里,并将epfd上该fd的事件清空。如果需要继续监听该fd,则需要使用EPOLL_CTL_MOD 添加需要监听的事件。因为没有清空epfd上的fd,所以不需要使用EPOLL_CTL_ADD.

    最后,水平触发(LT)是默认的工作模式,适合与阻塞和非阻塞socket, 错误率小。边缘出发(ET)是高速工作模式,只适用于非阻塞socket。

         

  • 相关阅读:
    编辑器1.0
    react native定报预披项目知识点总结
    placeholder中文字添加换行方法
    ios端position为fixed失效的解决办法
    利用fis3构建前端项目工程
    webpack学习记录
    webpack学习记录-认识loader(二)
    webpack学习记录-初步体验(一)
    去抖(节流)
    css布局:左边定宽、右边自适应
  • 原文地址:https://www.cnblogs.com/zengtx/p/11928188.html
Copyright © 2011-2022 走看看