[libevent源碼分析] event_init
來源:程序員人生 發布時間:2015-08-20 08:10:27 閱讀次數:4196次
libevent采取的是經典的reactor網絡框架,集成了信號、定時、網絡事件于1體
首先對event_init進行源碼剖析
event_init 主要創建event_base對象,
struct event_base {
const struct eventop *evsel; //lievent支持select epoll kequeue..等網絡api,包括init、add、del、dispatch的接口,每種網絡框架都支持
void *evbase; //支持相應網絡api的 結構對象,必須epoll就是epoll_create返回epfd相干的內容,
//由于每種網絡接口都不1樣,所以需要使用void*
int event_count; //總網絡事件數
int event_count_active; //激活事件數
int event_gotterm; //event_base_dispatch中終止while循環
int event_break; //event_base_dispatch終止while立刻
struct event_list **activequeues;//用于保存激活事件列表,是1個2維數組,第1維用于權限number,越低越高,第2維為激活列表
int nactivequeues; // 激活權限列表有多少個權限
struct evsignal_info sig; //保存著信號相干的內容
struct event_list eventqueue; //保存著注冊的事件列表
struct timeval event_tv; //用于和tv_cache肯定是不是時間被修改了,如果使用monotonic時間是不被修改的,gettimeofday才會用到
struct min_heap timeheap; //用于時間堆(最小堆)管理
struct timeval tv_cache;
};
代碼以下
struct event_base *
event_init(void)
{
struct event_base *base = event_base_new();
if (base != NULL)
current_base = base;//如果創建成功那末就會把current_base更新為新創建的base
return (base);
}
event_init 此函數用于對外提供接口,主要完成的初始化event_base對象,同時如果cc創建成功那末就把current_base指向新創建的event_base,用于默許event_base
下面是創建和初始化event_base全部函數
struct event_base *
event_base_new(void)
{
int i;
struct event_base *base;
//先創建1個even_base對象
if ((base = calloc(1, sizeof(struct event_base))) == NULL)
event_err(1, "%s: calloc", __func__);
event_sigcb = NULL;
event_gotsig = 0;
//檢測系統是不是可使用MONOTONIC time
detect_monotonic();
//填充base->event_tv記錄創建base的時間
gettime(base, &base->event_tv);
//初始化最小定時器堆,p n a都置為0
min_heap_ctor(&base->timeheap);
//初始化隊列first = NULL and last = &first
TAILQ_INIT(&base->eventqueue);
//初始化用于信號通訊的socket,使用的是sockpair unix網絡套接字
base->sig.ev_signal_pair[0] = ⑴;
base->sig.ev_signal_pair[1] = ⑴;
base->evbase = NULL;
for (i = 0; eventops[i] && !base->evbase; i++) {
//event會優先選擇epoll,這個數組是依照索引優先權降落
base->evsel = eventops[i];
base->evbase = base->evsel->init(base);
}
if (base->evbase == NULL)
event_errx(1, "%s: no event mechanism available", __func__);
if (getenv("EVENT_SHOW_METHOD"))
event_msgx("libevent using: %s
",
base->evsel->name);
/* allocate a single active event queue */
event_base_priority_init(base, 1);
return (base);
}
detect_monotonic用于檢測當前使用的時間更新機制,查看是不是可以調用clock_m_geeettime函數來設置use_monotonic
getttime用于初始化event_tv
min_head_ctor初始化最小堆數組結構,a n p
TAIL_INIT(&base->event_tv)用于初始化注冊事件雙向鏈表
全部for循環是為了選取最優的網絡接口模型,同時初始化這個網絡模型數據結構
下面是初始化激活網絡事件權限
int
event_base_priority_init(struct event_base *base, int npriorities)
{
int i;
if (base->event_count_active)
return (⑴);
//先釋放
if (base->nactivequeues && npriorities != base->nactivequeues) {
for (i = 0; i < base->nactivequeues; ++i) {
free(base->activequeues[i]);
}
free(base->activequeues);
}
/* Allocate our priority queues */
//先分配1維權限數組
base->nactivequeues = npriorities;
base->activequeues = (struct event_list **)calloc(base->nactivequeues,
npriorities * sizeof(struct event_list *));
if (base->activequeues == NULL)
event_err(1, "%s: calloc", __func__);
//再初始化2維激活事件列表
for (i = 0; i < base->nactivequeues; ++i) {
base->activequeues[i] = malloc(sizeof(struct event_list));
if (base->activequeues[i] == NULL)
event_err(1, "%s: malloc", __func__);
TAILQ_INIT(base->activequeues[i]);
}
return (0);
}
libeven 全部源碼分析和sample都在我的 githup
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈