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先被处理。

时间: 2024-10-08 10:45:34

Libevent源码分析—event_init()的相关文章

[libevent源码分析] event_init

libevent采用的是经典的reactor网络框架,集成了信号.定时.网络事件于一体 首先对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的 结构对象

【转】libevent源码分析

libevent源码分析 转自:http://www.cnblogs.com/hustcat/archive/2010/08/31/1814022.html 这两天没事,看了一下Memcached和libevent的源码,做个小总结. 1.入门 1.1.概述Libevent是一个用于开发可扩展性网络服务器的基于事件驱动(event-driven)模型的网络库.Libevent有几个显著的亮点: (1)事件驱动(event-driven),高性能:(2)轻量级,专注于网络,不如 ACE 那么臃肿庞

Libevent源码分析-timer和signal处理

timer处理 Signal处理 timerfd和signalfd timerfd signalfd timer处理 在Libevent源码分析-event处理流程中,使用了定时器,来看一下源码: evtimer_set(&ev, time_cb, NULL);//设置定时器事件 其中evtimer_set是个宏定义 #define evtimer_set(ev, cb, arg) event_set((ev), -1, 0, (cb), (arg)) //event_set原型 void ev

Libevent源码分析 (1) hello-world

Libevent源码分析 (1) hello-world ⑨月份接触了久闻大名的libevent,当时想读读源码,可是由于事情比较多一直没有时间,现在手头的东西基本告一段落了,我准备读读libevent的源码,凡是我觉得有必要的内容均一一记录,与君共勉. 首先要说说什么是libevent: libevent是一个事件通知库,libevent API提供一种机制使得我们可以在一个文件描述符(file descriptor)发生特定事件时或者timeout发生时执行指定的回调函数.libevent意

Libevent源码分析系列【转】

转自:https://www.cnblogs.com/zxiner/p/6919021.html 1.使用libevent库 源码那么多,该怎么分析从哪分析呢?一个好的方法就是先用起来,会用了,然后去看底层相应的源码,这样比较有条理,自上向下掌握.下面用libevent库写个程序,每隔1秒输出一行信息. test.c 2.event, event_base 经过第1步,下面开始看上面程序中的每一部分的源码.首先是两个核心结构体event和event_base event event_base源码

libevent源码分析-event

event结构 event相关接口 Libevent对event的管理 event结构 event是Reactor模式中的最重要的组件.它包含了了一个句柄fd,并设置监听这个句柄上的哪些事件(读/写等),设置了对应的函数指针,在事件到来时,回调函数指针来处理事件. 先看一下event的结构.它位于include/event2/event_struct.h中 struct event { TAILQ_ENTRY(event) ev_active_next; TAILQ_ENTRY(event) e

[libevent源码分析] event_set

libevent使用event来封装网络事件回调,参数.fd...等一些信息,函数很简单 void event_set(struct event *ev, int fd, short events, void (*callback)(int, short, void *), void *arg) { /* Take the current base - caller needs to set the real base later */ ev->ev_base = current_base; /

[libevent源码分析] event_add

event_add 把event往当前event中的ev_base追加,如果需要定时,那么tv不能为空 int event_add(struct event *ev, const struct timeval *tv) { struct event_base *base = ev->ev_base; //event_add 会把event加入到他的ev_base成员里 const struct eventop *evsel = base->evsel; //对应linux的epoll相关函数

[libevent源码分析] event_base_dispatch

分析下事件循环 event_base_dispatch int event_base_dispatch(struct event_base *event_base) { return (event_base_loop(event_base, 0)); } int event_base_loop(struct event_base *base, int flags) { const struct eventop *evsel = base->evsel; void *evbase = base->