zoukankan      html  css  js  c++  java
  • Linux epoll机制

    epoll_create、epoll_ctl、epoll_wait、close

     g++ 时加上, -pg  启用gprof,gcc编译的时候带上-pg参数即可, 参考:https://www.cnblogs.com/jluzhsai/p/3657820.html

    参考: https://www.cnblogs.com/lidan/archive/2011/05/25/2239517.html

        -O0       -O1       -O2       -O3  
    编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高

      -pipe  
    使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题

        -Wl.option  
    此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然后传递给会连接程序.

    在epoll 之前, 都是使用select来做事件触发。相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。因为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多。并且,linux/posix_types.h头文件有这样的声明:

    #define__FD_SETSIZE   1024
    表示select最多同时监听1024个fd,当然,可以通过修改头文件再重编译内核来扩大这个数目,或者是增加进程数,
    比如要监听100万个fd, 就要开1000000/1024个进程,显然不现实

    epoll的接口,一共就三个函数

    1.创建epoll句柄    

    #include <sys/epoll.h>
    int epoll_create1(int flags);
      替代了之前的epoll_create(int size);                                                            

    创建一个多路复用的实例,flags, 0:如果这个参数是0,这个函数等价于poll_create(0). 

    EPOLL_CLOEXEC:这是这个参数唯一的有效值,如果这个参数设置为这个。那么当进程替换映像的时候会关闭这个文件描述符,这样新的映像中就无法对这个文件描述符操作,适用于多进程编程+映像替换的环境里

    success:返回一个非0 的未使用过的最小的文件描述符
    error:-1 errno被设置

    2. 事件注册函数

    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) ;

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

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

    op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修改、EPOLL_CTL_DEL 删除

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

    event:指向epoll_event的指针, 告诉内核需要监听什么事件;

    succ返回0,不成功返回-1

    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 */ 

    };

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

             EPOLLIN:            触发该事件,表示对应的文件描述符上有可读数据。(包括对端SOCKET正常关闭);
             EPOLLOUT:         触发该事件,表示对应的文件描述符上可以写数据;
            EPOLLPRI:           表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
            EPOLLERR:        表示对应的文件描述符发生错误;
             EPOLLHUP:        表示对应的文件描述符被挂断;
            EPOLLET:           将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
            EPOLLONESHOT:  只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里。

    3.等待事件触发,该函数用于轮询I/O事件的发生, 类似于select()调用, 当超过timeout还没有事件触发时,就超时。

    int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);     
    epfd:由epoll_create 生成的epoll专用的文件描述符
    events用来从内核得到事件的集合,集合在events数组中,数组中实际存放的成员个数是函数的返回值。
    maxevents告之内核这个events有多大(数组成员的个数),
    参数timeout是超时时间(毫秒,0会立即返回,-1永久阻塞, 一般用-1即可)。

    返回0, 表示超时 

    epoll_wait运行的原理是:
    等侍注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中, 并 且将注册在epfd上的socket fd的事件类型给清空,
    所以如果下一个循环你还要关注这个socket fd的话,则需要用epoll_ctl(epfd,EPOLL_CTL_MOD,listenfd,&ev)来重新设置socket fd的事件类型。
    这时不用EPOLL_CTL_ADD,因为socket fd并未清空,只是事件类型清空。这一步非常重要。
     
     
    EPOLL事件有两种模型:

    Edge Triggered(ET)       //高速工作方式,错误率比较大,只支持no_block socket (非阻塞socket)
    LevelTriggered(LT)       //缺省工作方式,即默认的工作方式,支持blocksocket和no_blocksocket,错误率比较小。

  • 相关阅读:
    《中小学生Python编程入门指南》1.1 什么是编程
    《中小学生Python编程入门指南》前言
    简单的番茄工作法倒计时(源码)
    关于AE
    Blender2.5快捷键
    关于Blender
    随意设置控件每一个角的倒角
    关于多个block问题
    UICollectionViewCell--查找cell上的按钮点击后,对应的是哪个cell
    UIMenuItem
  • 原文地址:https://www.cnblogs.com/henryliublog/p/9645562.html
Copyright © 2011-2022 走看看