下面開始看初始化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先被處理。
