Libevent

Libevent2.1和两个重要结构体

Posted by Liangjf on April 14, 2019

Libevent2.1和两个重要结构体

老接口         新接口

event.h:        event2/event.h, event2/buffer.h event2/bufferevent.h event2/ tag.h

evdns.h:        event2/dns*.h

evhttp.h:       event2/http*.h

evrpc.h:        event2/rpc*.h

evutil.h:       event2/util*.h

在阅读Libevent源码时,会经常看到backend这个单词。其直译是“后端”。实际上其指的是Libevent内部使用的多路IO复用函数,多路IO复用函数就是select、poll、epoll这类函数

event结构体

    struct event {
        struct event_callback ev_evcallback; //回调函数
        //1.最小堆管理定时器时间
        union {
            TAILQ_ENTRY(event) ev_next_with_common_timeout;
            int min_heap_idx;
        } ev_timeout_pos;
        evutil_socket_t ev_fd;  //IO事件:绑定的文件描述符;Signal事件:绑定的信号
        //2.事件相关
        short ev_events;    //事件类型:I/O、信号、定时器事件
        short ev_res;   //当前激活事件的类型。调用回调函数时,传递给回调函数,保存回调函数的返回值
        //3.Reactor管理者
        struct event_base *ev_base;     //event所属的Reactor
        //4.io/signal事件链表
        union {
            /* used for io events */
            struct {
                LIST_ENTRY (event) ev_io_next;
                struct timeval ev_timeout;
            } ev_io;
            /* used by signal events */
            struct {
                LIST_ENTRY (event) ev_signal_next;
                short ev_ncalls;
                /* Allows deletes in callback */
                short *ev_pncalls;
            } ev_signal;
        } ev_;
        struct timeval ev_timeout;  //定时事件的超时值
    };

从这个结构体看出来,包括3个方面的东西:

  • 1.定时器相关
  • 2.事件
  • 3.Reactor管理者
  • 4.事件链表

功能涵盖:

  • 1.定时器事件
  • 2.IO事件
  • 3.信号事件

技巧

使用 union 來把IO、定時器、信号 三者合为一个结构体来管理,方便维护,并且是节省了内存的管理。这种做法在很多场景使用了,比如在内存池中,在内存池的各个槽的节点中包括了指向下个槽的地址,但是为了节省槽的结构体大小,会把next指针和节点数据用union封装起来,达到缩小结构体大小的目的。

ev_events的类型

  • #define EV_TIMEOUT      0x01        //超时事件
  • #define EV_READ         0x02        //读事件
  • #define EV_WRITE        0x04        //写事件
  • #define EV_SIGNAL       0x08        //信号事件
  • #define EV_PERSIST      0x10        //永久事件
  • #define EV_ET           0x20        //边缘触发事件
  • #define EV_FINALIZE     0x40    //结束事件
  • #define EV_CLOSED       0x80        //关闭事件

event_base结构体

struct event_base {
        const struct eventop *evsel;    //底层具体I/O demultiplex操作函数集
        void *evbase;   //底层base指针
        struct event_changelist changelist; //改变事件的链表
        const struct eventop *evsigsel;     //底层base使用的消息回调指针
        struct evsig_info sig;  //信号句柄号
        //对事件的一些统计
        int virtual_event_count;
        int virtual_event_count_max;
        int event_count;
        int event_count_max;
        int event_count_active;
        int event_count_active_max;
        int event_gotterm;
        int event_break;
        int event_continue;
        int event_running_priority;
        int running_loop;
        int n_deferreds_queued;
        //激活事件队列
        struct evcallback_list *activequeues;
        int nactivequeues;  //激活事件队列的长度
        //事件回调函数。注册是延迟注册,系统在合适时间绑定
        struct evcallback_list active_later_queue;
        //定时器超时事件相关
        struct common_timeout_list **common_timeout_queues;
        int n_common_timeouts;
        int n_common_timeouts_allocated;
        //io、信号、定时信号的底层存放数据结构
        struct event_io_map io; //io存放是map结构,查找快
        struct event_signal_map sigmap; //map结构
        struct min_heap timeheap;   //最小堆
        struct timeval tv_cache;
        struct evutil_monotonic_timer monotonic_timer;
        struct timeval tv_clock_diff;
        time_t last_updated_clock_diff;
    //涉及多线程的锁,条件变量,等待者等
    #ifndef EVENT__DISABLE_THREAD_SUPPORT
        unsigned long th_owner_id;
        void *th_base_lock; 
        void *current_event_cond;
        int current_event_waiters;
    #endif
        struct event_callback *current_event;
    #ifdef _WIN32
        struct event_iocp_port *iocp;
    #endif
        enum event_base_config_flag flags;
        //Reactor调度相关
        struct timeval max_dispatch_time;
        int max_dispatch_callbacks;
        int limit_callbacks_after_prio;
        int is_notify_pending;
        evutil_socket_t th_notify_fd[2];
        struct event th_notify;
        int (*th_notify_fn)(struct event_base *base);
        struct evutil_weakrand_state weakrand_seed;
        LIST_HEAD(once_event_list, event_once) once_events;
};