您的位置:首页 > 其它

libevent 主流程解析

2015-09-16 17:52 253 查看
struct event_base {

    /** Function pointers and other data to describe this event_base's

     * backend. */

    const struct eventop *evsel;//这是IO事件分离器,参考static const struct eventop *eventops[]。我这里用里面的epollops,epoll.c。

    /** Pointer to backend-specific data. */

    void *evbase;//epoll为例:里面的struct epoll_event *events;int nevents。在epoll_wait就会用到他。用来保存触发的IO和长度。

    /** 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;//signal event.evsigops。信号事件处理器。

    /** Data to implement the common signal handelr code. */

    struct evsig_info sig;//信号配对sock,信号事件处理器的参数。这对sock用于将收到信号时,发送给配对sock,配对sock可以通过IO分离器来处理。

    /** Number of virtual events */

    int virtual_event_count;

    /** Number of total events added to this event_base */

    int event_count;

    /** Number of total events active in this event_base */

    int event_count_active;

    /** Set if we should terminate the loop once we're done processing

     * events. */

    int event_gotterm;//这个和下面event_break是退出主循环的。

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

    /** Set if we're running the event_base_loop function, to prevent

     * reentrant invocation. */

    int running_loop;//0死循环。

    /* Active event management. lenth = nactivequeues*/

    /** An array of nactivequeues queues for active events (ones that

     * have triggered, and whose callbacks need to be called).  Low

     * priority numbers are more important, and stall higher ones.

     */

    struct event_list *activequeues;//一个队列,保存的已经触发的event_list组。以优先级为坐标。

    /** The length of the activequeues array */

    int nactivequeues;

    /* 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;//保存定时器hash-table(us最高4位为这个结构的标志,其次8位在这个hash定位)。

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

    /** List of defered_cb that are active.  We run these after the active

     * events. */

    struct deferred_cb_queue defer_queue;

    /** Mapping from file descriptors to enabled (added) events */

    struct event_io_map io;//这个保存io事件的hashtable(fd来定位)。一个fd可以添加多个事件。

    /** Mapping from signal numbers to enabled (added) events. */

    struct event_signal_map sigmap;//这个保存sig事件的hash(sig来定位)。一个sig可以添加多个事件。

    /** All events that have been enabled (added) in this event_base */

    struct event_list eventqueue;//一个链表,所有添加的事件都放在这里,但是我不明白,在io和sigmap,timeheap已经添加了,为什么还添加到这里。

    /** Stored timeval; used to detect when time is running backwards. */

    struct timeval event_tv;//保存上一次时间,现在再读取时间与他比较,是否时间倒退了。

    /** Priority queue of events with timeouts. */

    struct min_heap timeheap;//最小时间堆,和common_timeout_queues并行存在。我们在添加定时器加不加common flag,决定2种储存方式。如果最小堆过大,我们将新的超时可以用上面哪个结构。

    /** Stored timeval: used to avoid calling gettimeofday/clock_gettime

     * too often. */

    struct timeval tv_cache;

#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)

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

#endif

#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;

    /** The event whose callback is executing right now */

    struct event *current_event;

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

#ifdef WIN32

    /** IOCP support structure, if IOCP is enabled. */

    struct event_iocp_port *iocp;

#endif

    /** Flags that this base was configured with */

    enum event_base_config_flag flags;

    /* Notify main thread to wake up break, etc. */

    /** 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);//=evthread_notify_base_default

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct event {

    TAILQ_ENTRY(event) ev_active_next;//TAILQ_ENTRY是链表节点,可以通过不同的节点来连接不同类型的event。这个是用来连接激活(activequeues结构中)的事件。

    TAILQ_ENTRY(event) ev_next;//eventqueue所有事件都会用它来连接。eventqueue数据结构中。

    /* for managing timeouts */

    union {

        TAILQ_ENTRY(event) ev_next_with_common_timeout;//common结构的每个类型的超时的连接在这里。common_timeout_queues结构中

        int min_heap_idx;//如果用的是最小堆,这个用来表示timeheap结构中的位置。

    } ev_timeout_pos;

    evutil_socket_t ev_fd;//IO是fd,sig是具体信号,定时器为-1

    struct event_base *ev_base;//base

    union {

        /* used for io events */

        struct {

            TAILQ_ENTRY(event) ev_io_next;//在event_io_map结构中,用这个节点来连接,一个fd可以有多个事件。

            struct timeval ev_timeout;//每一个时间都可以有超时(在event_add的时候,tv为超时时间,会把tv添加到时间堆里面),如果超时或者事件发生,用这个重载事件。

        } ev_io;

        /* used by signal events */

        struct {

            TAILQ_ENTRY(event) ev_signal_next;//每个信号的多个事件,用他来连接。

            short ev_ncalls;//如果是信号,可以多次调用回调函数。信号sock的回调函数evsig_cb表面,信号接收到几次,执行几次回调。

            /* Allows deletes in callback */

            short *ev_pncalls;//指向ev_ncalls

        } ev_signal;

    } _ev;

    short ev_events;//事件类型:(EV_READ|EV_WRITE|EV_SIGNAL,EV_TIMEOUT,EV_PERSIST(新建时添加,表示事件发生后继续监听))

    short ev_res;//表示被什么触发callback。在事件发生或者超时时被标记,在callback作为参数传进去。EV_TIMEOUT,EV_READ,EV_WRITE,EV_SIGNAL

    short ev_flags;//将事件注册到哪个数据结构中EVLIST_INSERTED到eventqueue,EVLIST_TIMEOUT到时间堆,EVLIST_ACTIVE到发生事件activequeues...

    ev_uint8_t ev_pri;    //优先级,在activequeues中用他来设置事件执行的先后

    ev_uint8_t ev_closure;//新建事件时标记。sig标志为EV_CLOSURE_SIGNAL,ev_events表职位EV_CLOSURE_PERSIST(表示事件发生继续监听),否则用EV_CLOSURE_NONE。决定了callback之前处理超时重载,sig多次执行callback。

    struct timeval ev_timeout;//如果事件有超时,保存到期时间= now + _ev.ev_io.ev_timeout

    /* allows us to adopt for different types of events */

    void (*ev_callback)(evutil_socket_t, short, void *arg);//callback

    void *ev_arg;//事件参数,callback用到,在event_set或者event_new添加

}

几个数据结构:

1:链表,有个头,next指向下个节点,pre指向上一个节点的next的地址。

2.hashtable:fd作为key(fd)查找hash的位置,用链表保存重复key,每个fd节点有个事件链表,保存不同事件。

3.hash:sig的值作为key,直接找到位置,每个sig节点有多个事件

4.heap:最小堆,数组保存定时器或者超时。用到期时间存储,通过比较来触发和调整堆。

1.

event_init/event_base_new

初始化结构体,选择事件分离器,假设为epollops,

调用base->evbase = base->evsel->init(base);来初始化epoll_create,然后调用:evsig_init(base);

evsig_init函数调用了evutil_socketpair建立sig配对sock,并用event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1],EV_READ | EV_PERSIST, evsig_cb, base);来进行sig的IO处理。evsig_cb是来调用注册sig的回调函数。

2.

event_assign初始化event数据结构,新添一个事件evsignal_new,evtimer_new,event_set最终都是调用他。将fd,callback,读写-持续标志写入事件。

3.

event_add,调用evmap_io_add(添加到io的hashtable数据结构中),evmap_signal_add(添加到sig-hash中),分别调用用epoll_ctl和sigaction(回调函数将收到的信号发送给base->sig.ev_signal_pair[1],然后通过evsig_cb处理),超时或者定时器注册(添加到最小堆或者common中。)

4.

event_dispatch调用event_base_loop:res = evsel->dispatch(base, tv_p);处理epoll_wait,并添加激活事件到activequeues;用timeout_process(base);检测超时,添加到activequeues中。event_process_active处理activequeues中的事件callback。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: