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先被处理。
脚踏实地、积极思考