Libevent源碼分析—event_init()


下面開始看初始化event_base結構的相關函數。相關源碼位於 event.c

event_init()

首先調用event_init()初始化event_base結構體
struct event_base *
event_init(void)
{
    struct event_base *base = event_base_new();    //event_init()調用event_base_new()
    if (base != NULL)
        current_base = base;
    return (base);
}

我們發現event_init()工作量很少,只是調用event_base_new()函數,所以真正初始化event_base的工作是在event_base_new()函數內完成。

event_base_new()

struct event_base *
event_base_new(void)    //初始化libevent的event_base
{
    int i;
    struct event_base *base;
    if ((base = calloc(1, sizeof(struct event_base))) == NULL)    //在堆上分配內存存儲event_base,所有字段初始化為0
        event_err(1, "%s: calloc", __func__);
    event_sigcb = NULL;
    event_gotsig = 0;
    detect_monotonic();    //設置use_monotonic變量
    gettime(base, &base->event_tv);    //base->tv_cache.tv_sec非0,則賦給base->event_tv
    
    min_heap_ctor(&base->timeheap);    //初始化定時事件的小根堆base->timeheap    min_heap.h
    TAILQ_INIT(&base->eventqueue);    //初始化注冊事件鏈表base->eventqueue    sys/queue.h
    base->sig.ev_signal_pair[0] = -1;    //初始化信號base->sig
    base->sig.ev_signal_pair[1] = -1;
    
    base->evbase = NULL;    //初始化I/O多路復用 base->evbase
    //遍歷全局數組eventops[],初始化libevent的I/O多路復用機制
    for (i = 0; eventops[i] && !base->evbase; i++) {    //以NULL標志數組結尾,只選取一個I/O多路復用機制
        base->evsel = eventops[i];    //初始化base->evsel
        base->evbase = base->evsel->init(base);    //初始化base->evbase
    }
    if (base->evbase == NULL)    //沒有I/O多路復用
        event_errx(1, "%s: no event mechanism available", __func__);
    if (evutil_getenv("EVENT_SHOW_METHOD")) //調用getenv()獲取環境變量EVENT_SHOW_METHOD    evutil.c
        event_msgx("libevent using: %s\n",
               base->evsel->name);
    /* allocate a single active event queue */
    //event_base_new()內調用event_base_priority_init()
    event_base_priority_init(base, 1);    //設置優先級base->nactivequeues;分配數組base->activequeues。數組大小和優先級相同
    return (base);
}

其中由3點需要注意:

1.該函數調用calloc()在堆上分配內存來存儲event_base;

2.使用全局數組eventops[]存儲系統支持的I/O多路復用機制,然后遍歷該數組,選取第1個I/O多路復用機制。

3.libevent支持event有優先級,所以又調用了event_base_priority_init()來完成優先級相關的設置。

event_base_priority_init()

//設置不同event的優先級,值越小,優先級越高
//返回值:0,成功;-1,出錯
int
event_base_priority_init(struct event_base *base, int npriorities)
{
    int i;
    if (base->event_count_active)    //當前base上有活躍的events則不能設置優先級,返回。
        return (-1);
    if (npriorities == base->nactivequeues)    //設置的優先級和當前優先級相同,則直接返回
        return (0);
    if (base->nactivequeues) {    //不同,則先釋放原先的activequeues數組
        for (i = 0; i < base->nactivequeues; ++i) {
            free(base->activequeues[i]);
        }
        free(base->activequeues);
    }
    /* Allocate our priority queues */
    base->nactivequeues = npriorities;    //設置新的優先級
    base->activequeues = (struct event_list **)
        calloc(base->nactivequeues, sizeof(struct event_list *));    //設置和優先級值相同大小的event_list數組
    if (base->activequeues == NULL)
        event_err(1, "%s: calloc", __func__);
    for (i = 0; i < base->nactivequeues; ++i) {
        base->activequeues[i] = malloc(sizeof(struct event_list));    //初始化activequeues數組中每個元素
        if (base->activequeues[i] == NULL)
            event_err(1, "%s: malloc", __func__);
        TAILQ_INIT(base->activequeues[i]);
    }
    return (0);
}

該函數設置優先級,初始化了event_base的nactivequeues成員和activequeues成員。優先級值越小,優先級越高。在活躍事件鏈表中,優先級高的event先被處理。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM