设为首页 加入收藏

TOP

Libevent浅析(一)
2017-10-11 15:46:02 】 浏览:8143
Tags:Libevent 浅析

前段时间对Libevent的源码进行了阅读,现整理如下:

介绍

libevent是一个轻量级的开源高性能事件驱动网络库,是一个典型的Reactor模型。其主要特点有事件驱动,高性能,跨平台,统一事件源等等。
网上关于libevent的源码分析有很多相关博客,本人在学习过程中也是借助了网络。所以,在此,关于libevent中的许多具体实现部分就不做介绍,主要是从相关数据结构层面上去分析。仅供参考。

event结构体

  • libevent中的事件处理类型是event结构类型,event结构体封装了句柄,事件类型,回调函数,以及其他必要的标志和数据,是整个libevent库的核心。
  • 该结构的定义如下:

    struct event{
        /*
     * ev_next, ev_active_next都是双向链表节点指针
     * 它们是libevent对不同事件类型和在不同时期,对事件的管理时使用到的字段
     *
     * libevent使用双向链表保存所有注册的IO和signal事件
     * ev_next 就是该IO事件在链表中的位置,称此链表为已注册事件链表
     * ev_active_next: libevent将所有激活事件放入链表active list中,然后遍历active list
     * 执行调度,ev_active_next就指明了event在active list中的位置
     */
        TAILQ_ENTRY(event) ev_next;
        TAILQ_ENTRY(event) ev_active_next;
    
        /*
     * _ev 是一个联合体,所有具有相同描述符的IO事件通过ev.ev_io.ev_io_next成员串联成一个
     * 尾队列,称之为IO事件队列,所有具有相同信号值的信号事件通过ev.ev_signal.ev_signal_next
     * 串联成一个尾队列,称之为信号事件队列。ev.ev_signal.ev_ncalls成员指定时间发生时,Reactor
     * 需要执行多少次该事件对应的回调函数,ev.ev_signal.ev_pcalls要么是NULL,要么执行ev.ev_signal.ev_ncalls
     */
        union{
            struct {
                TAILQ_ENTRY(event) ev_io_next;
                struct timeva l ev_timeout;
            }ev_io;
    
            struct {
                TAILQ_ENTRY(event) ev_signal_next;
                short ev_ncalls;
                short *ev_pcalls;
            }ev_signal;
        } _ev;
    
        /*
     * ev_timeout_pos是一个联合体,它仅用于定时事件处理器,老版本libevnet中使用最小堆管理
     * 定时器,但是开发者认为有时简单链表的管理更加高效。所以新版本中引入了“通用定时器”的
     * 概念。这些定时器不是存储在时间堆中,而是存储在尾队列中,我们称之为通用定时器队列。
     * 对于通用定时器而言,ev_timeout_pos中的ev_next_with_common_timeout成员指出了该定时器
     * 在队列中的位置;对于其他定时器,min_heap_idx成员指出了该定时器在时间堆中的位置。一个
     * 定时器是否是通用定时器,取决于其超时值的大小。具体参考event.c中的is_common_timeout函数。
     */
        union{
            TAILQ_ENTRY(event) ev_next_with_common_timeout;
            int min_heap_idx;
        }ev_timeout_pos;
    
        //如果是超时事件ev_timeout超时值
        struct timeva l ev_timeout;
    
        //ev_base :该事件所属的反应堆实例,这是一个event_base结构体
        struct event_base *ev_base;
    
        //对于IO事件,是绑定的文件描述符,对于signal事件,是绑定的信号
        int ev_fd;
    
        /*
     * ev_events : event关注的事件类型,它可以是以下三种类型:
     * IO事件:EV_WRITE / EV_READ
     * 定时事件: EV_TIMEOUT 
     * 信号: EV_SIGANL
     *辅助选项: EV_PERSIST, 表明是一个永久事件
     */
        short ev_events;  //各个事件可以使用 "|"运算符进行组合,信号和IO事件不能同时设置
    
        //事件就绪执行时,调用ev_callback的次数,通常为1
        short ev_ncalls;
    
        //指针,指向ev_ncalls或NULL
        short *ev_pncalls;  //allows deletes in callback
    
        int ev_pri;  //smaller numbers are higher priority
    
        //ev_callback:event回调函数,被ev_base调用,执行事件处理程序,这是一个函数指针
        //其中fd对应ev_fd, events对应ev_events, arg对应ev_arg
        void (*ev_callback)(int , short, void *arg);
    
        //void* 表明可以是任意类型,在设置event时指定
        void *ev_arg;
    
        //记录了当前激活事件的类型
        int ev_res;   //result passed to event callback
    
        /*
     * libevent用于标记event信息的字段,表明当前的状态
     */
        int ev_flags;
    };

    从event结构的定义可以看出,event中封装了句柄,回调函数,和事件类型。包括该事件在相应链表或时间堆中的索引位置。宏TAILQ_ENTRY是尾队列的节点类型,其定义为:

    #define TAILQ_ENTRY(type) \
     struct { \
     struct type *tqe_next; \ /*下一个元素*/ 
            struct type **tqe_prev; \ /*前一个元素的地址*/  
        }
  • 每当有事件event转变为就绪状态时,libevent就会把它移入到active event list[priority]中,其中priority是event的优先级;接着libevent会根据自己的调度策略选择就绪事件,调用其cb_callback()函数执行事件处理。

事件处理框架 event_base

  • 结构体event_base是libevent的Reactor,其声明如下:

    struct event_base {
        /* 初始化Reactor的时候选择一种后端IO复用机制,并记录在如下字段中*/
        const struct eventop *evsel;
    
        /*指向IO复用机制真正存储的数据,它通过evsel成员的init函数来初始化*/
        void *evbase;
    
        /* 指向信号的后端处理机制,目前仅在signal.h文件中定义了一种处理方法*/
        const struct eventop *evsigsel;
        void *evsigbase;
    
        /*信号处理器使用到的数据结构,其中封装了一个socketpair创建的管道,它用于信号处理函数和事件多路分发器之间的通信。*/
        struct evsig_info sig;
    
        /* 添加到该event_base的所有事件和激活事件的数
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇2632 非常好友 下一篇2851 菜菜买气球

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目