Libevent 事件生成
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Libevent 事件生成相关的知识,希望对你有一定的参考价值。
事件堆实例生成:
struct event_base * event_base_new(void) { struct event_base *base = NULL; struct event_config *cfg = event_config_new(); if (cfg) { base = event_base_new_with_config(cfg); event_config_free(cfg); } return base; } event_config 结构如下 struct event_config { TAILQ_HEAD(event_configq, event_config_entry) entries; int n_cpus_hint; struct timeval max_dispatch_interval; int max_dispatch_callbacks; int limit_callbacks_after_prio; enum event_method_feature require_features; enum event_base_config_flag flags; }; struct event_base * event_base_new_with_config(const struct event_config *cfg) { int i; struct event_base *base; if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) { event_warn("%s: calloc", __func__); return NULL; } if (cfg) base->flags = cfg->flags; should_check_environment = !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV)); { struct timeval tmp; int precise_time = cfg && (cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER); int flags; if (should_check_environment && !precise_time) { precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL; base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER; } flags = precise_time ? EV_MONOT_PRECISE : 0; evutil_configure_monotonic_time_(&base->monotonic_timer, flags); gettime(base, &tmp); } //初始化小根堆 min_heap_ctor_(&base->timeheap); base->sig.ev_signal_pair[0] = -1; base->sig.ev_signal_pair[1] = -1; base->th_notify_fd[0] = -1; base->th_notify_fd[1] = -1; TAILQ_INIT(&base->active_later_queue); //初始化io singal哈系表 evmap_io_initmap_(&base->io); evmap_signal_initmap_(&base->sigmap); event_changelist_init_(&base->changelist); base->evbase = NULL; if (cfg) {
//初始化base的dispatch 时间间隔 -1 影响epoll select poll 阻塞时间参数 memcpy(&base->max_dispatch_time, &cfg->max_dispatch_interval, sizeof(struct timeval)); base->limit_callbacks_after_prio = cfg->limit_callbacks_after_prio; } else { base->max_dispatch_time.tv_sec = -1; base->limit_callbacks_after_prio = 1; } if (cfg && cfg->max_dispatch_callbacks >= 0) { base->max_dispatch_callbacks = cfg->max_dispatch_callbacks; } else { base->max_dispatch_callbacks = INT_MAX; } if (base->max_dispatch_callbacks == INT_MAX && base->max_dispatch_time.tv_sec == -1) base->limit_callbacks_after_prio = INT_MAX; // 选用事件模型 select poll devpoll 或者epoll
// eventops 定义选取合适模型 for (i = 0; eventops[i] && !base->evbase; i++) { if (cfg != NULL) { /* determine if this backend should be avoided */ if (event_config_is_avoided_method(cfg, eventops[i]->name)) continue; if ((eventops[i]->features & cfg->require_features) != cfg->require_features) continue; } /* also obey the environment variables */ if (should_check_environment && event_is_method_disabled(eventops[i]->name)) continue; //指向某个模型 如epoll base->evsel = eventops[i]; //evbase 指向初始化完成的实例 base->evbase = base->evsel->init(base); } if (base->evbase == NULL) { event_warnx("%s: no event mechanism available", __func__); base->evsel = NULL; event_base_free(base); return NULL; } if (evutil_getenv_("EVENT_SHOW_METHOD")) event_msgx("libevent using: %s", base->evsel->name); /* allocate a single active event queue */ if (event_base_priority_init(base, 1) < 0) { event_base_free(base); return NULL; } /* prepare for threading */ //有关多线程的base 初始化 return (base); }
大致就时base_event 的初始化, 选取一个io复用模型, Linux下优先选择epoll。
事件生成event_new:
int event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg) { if (!base) base = current_base; if (arg == &event_self_cbarg_ptr_) arg = ev; event_debug_assert_not_added_(ev); ev->ev_base = base; ev->ev_callback = callback; ev->ev_arg = arg; ev->ev_fd = fd; ev->ev_events = events; ev->ev_res = 0; ev->ev_flags = EVLIST_INIT; ev->ev_ncalls = 0; ev->ev_pncalls = NULL; if (events & EV_SIGNAL) { if ((events & (EV_READ|EV_WRITE|EV_CLOSED)) != 0) { event_warnx("%s: EV_SIGNAL is not compatible with " "EV_READ, EV_WRITE or EV_CLOSED", __func__); return -1; } ev->ev_closure = EV_CLOSURE_EVENT_SIGNAL; } else { if (events & EV_PERSIST) { evutil_timerclear(&ev->ev_io_timeout); ev->ev_closure = EV_CLOSURE_EVENT_PERSIST; } else { ev->ev_closure = EV_CLOSURE_EVENT; } } //初始化ev中的小根堆索引为 -1 min_heap_elem_init_(ev); if (base != NULL) { /* by default, we put new events into the middle priority */ ev->ev_pri = base->nactivequeues / 2; } event_debug_note_setup_(ev); return 0; }
以上是关于Libevent 事件生成的主要内容,如果未能解决你的问题,请参考以下文章