zoukankan      html  css  js  c++  java
  • Libevent(2.1.8)中的事件结构和管理

    Libevent(2.1.8)中的事件结构体

    这里的libevent版本为 2.1.8 。 libevent中事件的结构体struct event,定义在event_struct.h 中, 这里我们简单看一下:

    struct event {
        struct event_callback ev_evcallback; //事件的回调函数
    
        /* for managing timeouts */
        union {
            TAILQ_ENTRY(event) ev_next_with_common_timeout;// 链表形式管理定时 之前只用最小堆管理超时
            int min_heap_idx; //最小堆 管理超时事件
        } ev_timeout_pos;// 二选一
        evutil_socket_t ev_fd; // io事件时为关心的文件描述符,信号事件时为信号值
    
        struct event_base *ev_base;// 所属事件堆的实例
    
        union {
            /* used for io events */
            struct {
                LIST_ENTRY (event) ev_io_next;
                struct timeval ev_timeout;
            } ev_io;  //这部分指io事件时 所关心的同一描述符下,所有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_;
    
        short ev_events;     //事件的类型  可读可写 超时等
        short ev_res;        /* result passed to event callback */
        struct timeval ev_timeout; //事件超时时间
    };

    这里可以看到这个版本下的event 结构体比之前的好像少了不少东西, 如之前的结构:

    //event提供了函数接口,供Reactor在事件发生时调用,以执行相应的事件处理,
    //通常它会绑定一个有效的句柄(ev_fd)做为回调函数的参数.
    struct event {
        //已注册事件队列入口
        TAILQ_ENTRY (event) ev_next;
        //已激活事件队列入口
        TAILQ_ENTRY (event) ev_active_next;
        //信号事件队列入口 不过在以前的分析中可以看到,将来这个队列中的内容会被添加到ev_active_next队列中。
        TAILQ_ENTRY (event) ev_signal_next;
        //表示该event在定时器事件最小堆min_heap的索引
        unsigned int min_heap_idx;    /* for managing timeouts */
        //该事件所属的反应堆实例
        struct event_base *ev_base;
        //对于I/O事件,是绑定的文件描述符; 对于signal事件,是绑定的信号.
        int ev_fd;
    
        //表示事件类型: I/O,定时器或者信号
        short ev_events;
    
        //事件就绪执行时,将要调用ev_callback 的次数,通常为1
        short ev_ncalls;
    
        //该事件的超时时间,在定时器最小堆min_heap操作中作为节点值进行比较.
        struct timeval ev_timeout;
    
        //该事件的优先级,越小越优先.
        int ev_pri;        /* smaller numbers are higher priority */
    
        //该事件被激活时的回调函数
        void (*ev_callback)(int, short, void *arg);
    
        //该事件的标记信息,表示其当前的状态,即它在哪个链表中
        int ev_flags;
    
        ... //其他成员.
    };

    这里可以看到在老版本的libevent 中event结构体中有回调函数, 参数,优先级参数, 新版本中都被定义在了struct event_callback ev_evcallback;中 如下:

    struct event_callback {
        TAILQ_ENTRY(event_callback) evcb_active_next;
        short evcb_flags;     //选择回调类型 由以下四种
        ev_uint8_t evcb_pri;    /* smaller numbers are higher priority */
        ev_uint8_t evcb_closure; 
        /* allows us to adopt for different types of events */
            union {
            void (*evcb_callback)(evutil_socket_t, short, void *);
            void (*evcb_selfcb)(struct event_callback *, void *);
            void (*evcb_evfinalize)(struct event *, void *);
            void (*evcb_cbfinalize)(struct event_callback *, void *);
        } evcb_cb_union;
        void *evcb_arg;
    };

    比起老版本 新版本又丢弃了TAILQ_ENTRY(event) ev_next; 已注册事件队列入口   ev_active_next 已激活队列入口 ev_signal_next 信号事件队列入口等结构。

    Libevent 事件堆实例结构体:

    新版本的struct base_event 如下:

    struct event_base {
        /** Function pointers and other data to describe this event_base's
         * backend. */
        const struct eventop *evsel;//具体事件处理模型结构(select /poll/epoll)指针
        /** Pointer to backend-specific data. */
        void *evbase;//指向IO复用的真正操作 通过evsel来初始化
    
        /** List of changes to tell backend about at next dispatch.  Only used
         * by the O(1) backends. */
        struct event_changelist changelist; //???????后续
    
        /** Function pointers used to describe the backend that this event_base
         * uses for signals */
        const struct eventop *evsigsel;//信号操作
        /** Data to implement the common signal handelr code. */
        struct evsig_info sig;
    
        /** Number of virtual events */
        int virtual_event_count; //??????后续
        /** Maximum number of virtual events active */
        int virtual_event_count_max; //?????
        /** Number of total events added to this event_base */
        int event_count;   //事件总数
        /** Maximum number of total events added to this event_base */
        int event_count_max;//事件堆最多的事件数量
        /** Number of total events active in this event_base */
        int event_count_active; 
        /** Maximum number of total events active in this event_base */
        int event_count_active_max;
    
        /** Set if we should terminate the loop once we're done processing
         * events. */
        int event_gotterm; //处理完事件后是否终止
        /** Set if we should terminate the loop immediately */
        int event_break; //是否马上终止事件循环
        /** Set if we should start a new instance of the loop immediately. */
        int event_continue; //是否马上开始实例
    
        /** The currently running priority of events */
        int event_running_priority;  //当前running 事件的优先级
    
        /** Set if we're running the event_base_loop function, to prevent
         * reentrant invocation. */
        int running_loop; //是否正在loop event
    
        /** Set to the number of deferred_cbs we've made 'active' in the
         * loop.  This is a hack to prevent starvation; it would be smarter
         * to just use event_config_set_max_dispatch_interval's max_callbacks
         * feature */
        int n_deferreds_queued;
    
        /* Active event management. */
        /** An array of nactivequeues queues for active event_callbacks (ones
         * that have triggered, and whose callbacks need to be called).  Low
         * priority numbers are more important, and stall higher ones.
         */
        //已激活的回调事件队列  即event_callback 结构的队列
    struct evcallback_list *activequeues; /** The length of the activequeues array */ int nactivequeues; //激活队列长度 /** A list of event_callbacks that should become active the next time * we process events, but not this time. */ struct evcallback_list active_later_queue;// 下次激活的事件队列? /* common timeout logic */     //超时事件链表与小根堆配合使用 /** An array of common_timeout_list* for all of the common timeout * values we know. */ struct common_timeout_list **common_timeout_queues; /** The number of entries used in common_timeout_queues */ int n_common_timeouts; /** The total size of common_timeout_queues. */ int n_common_timeouts_allocated; /** Mapping from file descriptors to enabled (added) events */ struct event_io_map io;//存储io 事件 /** Mapping from signal numbers to enabled (added) events. */ struct event_signal_map sigmap;//存储信号事件 /** Priority queue of events with timeouts. */ struct min_heap timeheap;//小根堆 /** Stored timeval: used to avoid calling gettimeofday/clock_gettime * too often. */ struct timeval tv_cache; struct evutil_monotonic_timer monotonic_timer; /** Difference between internal time (maybe from clock_gettime) and * gettimeofday. */ struct timeval tv_clock_diff; /** Second in which we last updated tv_clock_diff, in monotonic time. */ time_t last_updated_clock_diff; #ifndef EVENT__DISABLE_THREAD_SUPPORT   //多线程支持 /* threading support */ /** The thread currently running the event_loop for this base */ unsigned long th_owner_id; /** A lock to prevent conflicting accesses to this event_base */ void *th_base_lock; /** A condition that gets signalled when we're done processing an * event with waiters on it. */ void *current_event_cond; /** Number of threads blocking on current_event_cond. */ int current_event_waiters; #endif /** The event whose callback is executing right now */ struct event_callback *current_event; /** Flags that this base was configured with */
    //这里后续的event config 会讲到
    enum event_base_config_flag flags; struct timeval max_dispatch_time; int max_dispatch_callbacks; int limit_callbacks_after_prio; /* Notify main thread to wake up break, etc. */
      //多线程   主线程loop过程中一般会阻塞 
      //若这时添加或者删除事件的话, 就需要唤醒阻塞的主线程, 加入了一个未决状态
    /** True if the base already has a pending notify, and we don't need * to add any more. */ int is_notify_pending; /** A socketpair used by some th_notify functions to wake up the main * thread. */ evutil_socket_t th_notify_fd[2]; /** An event used by some th_notify functions to wake up the main * thread. */ struct event th_notify; /** A function used to wake up the main thread from another thread. */ int (*th_notify_fn)(struct event_base *base);//唤醒主线程的函数指针 /** Saved seed for weak random number generator. Some backends use * this to produce fairness among sockets. Protected by th_base_lock. */ struct evutil_weakrand_state weakrand_seed; /** List of event_onces that have not yet fired. */ LIST_HEAD(once_event_list, event_once) once_events; };

    对于事件的存储 老版本中用队列来存储, 在新版本中使用哈希表map 如event_io_map , event_signal_map结构。还有一些多线程支持的参数后续会看到它们的用途。后续还会详细解释其中的各个字段含义。

      

  • 相关阅读:
    Cobbler学习之一--Fedora17下配置Cobbler安装环境
    linux下 tar解压 gz解压 bz2等各种解压文件使用方法
    linux性能检测工具
    firefox的plugin-container进程关闭方法
    部署额外域控制器,Active Directory
    利用yum下载软件包的三种方法
    HP iLo2 试用序列号
    (转)Linux下root密码丢失和运行级别错误的解决办法
    linux下的5个查找命令
    (转)CentOs上配置samba服务
  • 原文地址:https://www.cnblogs.com/MaAce/p/7809577.html
Copyright © 2011-2022 走看看