event 初始化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Function_Dou/article/details/87891347

在前面我们对整个libevent重要的核心(eventevent_base)结构做了分析, 处于茫然你现在跟着再来看一下event的初始化过程, 以及事件的注册/注销过程.

event 初始化

event的成员有很多, 所以我们需要对event初始化操作做一个简单的封装才行, 不然用户怎么可能不会记错记混这些参数呢.

event初始化函数是 event_set.

void event_set(struct event *ev, int fd, short events,void (*callback)(int, short, void *), void *arg);

长长的一串…这下event函数的参数又要会过去看event结构才行(经常要回过去看eventevent_base结构)

参数

  1. ev : 要初始化的event结构
  2. fd : 如果是IO就是文件描述符, 信号就传入信号即可. 如果是定时事件则传入 -1
  3. events : 监听事件的类型. 如 EV_READ. EV_TIMEOUT, EV_SIGNAL等.
  4. callback : 回调函数
  5. arg : 回调函数的第三个参数.

函数能看到要出初始化的成员很少, 其他的优先级等成员就是默认设置, 现在我们来看一个源码.

源码位置 event.c

// 设置event 结构, 初始化
// fd : 文件描述符
// events : 设置监听事件
// callback : 设置回调函数. 
// arg : 设置回调函数的第三个参数
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 */
	// 通过默认设置的 current_base 初始化
	ev->ev_base = current_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;	// 调用次数为0
	ev->ev_pncalls = NULL;

	min_heap_elem_init(ev);

	/* by default, we put new events into the middle priority */
	// 设置初始优先级
	if(current_base)
		ev->ev_pri = current_base->nactivequeues/2;
}

看到了吗, 整个event_set函数就是将成员变量进行初始, 大部分都是我们函数传入的参数, 其他没有被传入的参数就是默认设置的值. 比如 : ev_flags默认设置就是EVLIST_INIT表示ev被初始化过.

函数有有三个部分需要分析一下 :

  1. min_heap_elem_init(ev) : 其实默认设置成 -1. 表示没有设置计时器.

    void min_heap_elem_init(struct event* e) { e->min_heap_idx = -1; }
    
  2. current_base : 这个变量我们没有讲过, 而且它是凭空出现的. 其实current_base是libevent定义的一个event_base全局变量. 这个我们待会来分析.

  3. ev->ev_pri : 默认设置的为全局变量优先级个数的一半.

可以发现大部分成员都被默认初始化了, 但是如果想要重新初始化event_base参数或者其他参数不想默认初始化的怎么办. 没关系, libevent也有其他函数初始化个被成员的.

// 重新设置 ev 中的event_base成员
int
event_base_set(struct event_base *base, struct event *ev)
{
    /* Only innocent events may be assigned to a different base */
    // 如果ev没有被初始化, 则出错
    if (ev->ev_flags != EVLIST_INIT)
        return (-1);

    ev->ev_base = base;
    ev->ev_pri = base->nactivequeues/2;

    return (0);
}

event_base_set需要注意ev必须被初始化过才能重新设置.

// 重新设置 ev 优先级
int
event_priority_set(struct event *ev, int pri)
{
        // 如果当前事件已经处于激活状态了,则无法改变优先级了
        if (ev->ev_flags & EVLIST_ACTIVE)
                return (-1);
        // 如果传入的pri的大小不符合则退出
        if (pri < 0 || pri >= ev->ev_base->nactivequeues)
                return (-1);
        //设置优先级
        ev->ev_pri = pri;

        return (0);
}

event_priority_set 注意ev如果已经就绪了就不能再设置优先级而且设置的优先级必须合理才行.

current_base

libevent定义的一个全局变量struct event_base current_base = NULL. 由函数event_init初始化.

struct event_base *
event_init(void)
{
	struct event_base *base = event_base_new();

	if (base != NULL)
		current_base = base;

	return (base);
}

event_init主要调用的是event_base_new函数. 现在是初始化明白就行了, 因为event_base_new等到我们之后分析信号之后再来讲比较好.

总结

原计划是还要分析完注册和注销, 但是看来篇幅还是不够, 我们下节来分析吧.

  • libevent有一个全局event_base. current_base.
  • event_set函数.

猜你喜欢

转载自blog.csdn.net/Function_Dou/article/details/87891347
今日推荐