event 激活

本文详细探讨了libevent中的event激活过程,包括event_active函数和event_process_active激活函数的运作方式。event_active函数首先检查事件是否已存在于就绪队列,然后设置激活类型和调用次数,并将事件添加到就绪链表。而event_process_active函数从优先级队列开始遍历,触发回调函数执行。需要注意的是,高优先级事件可能会因为优先级为0的队列未清空而被饿死,这表明数值越小的优先级实际上更高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在之前我们分析了event的注册和注销, 而本节就来分析event又是如何被激活的.

event 激活

event_active 函数
// 将 event 事件主动设置到活动队列中
void
event_active(struct event *ev, int res, short ncalls)
{
	/* We get different kinds of events, add them together */
	// 如果事件已经在就绪队列中, 则更新返回事件的状态
	if (ev->ev_flags & EVLIST_ACTIVE) {
		ev->ev_res |= res;
		return;
	}

	// 设置事件的状态并将事件添加到就绪队列中
	ev->ev_res = res;
	ev->ev_ncalls = ncalls;	// 设置事件来临的总次数
	ev->ev_pncalls = NULL;
	event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
}
  1. 检查事件是否已经处于就绪队列中, 如果是则直接退出;
  2. 否则设置事件激活的类型以及事件被调用的次数
  3. 最后添加到就绪链表中

咋一看event_active只是主动的将事件加入到就绪队列中啊, 并没被激活啊. 下面就来分析激活函数

event_process_active 激活函数
// 处理所有的优先级队列中的事件, 并对每一个事件调用回调函数
// 但是总是先处理低优先级, 高优先级可能会被饿死
static void
event_process_active(struct event_base *base)
{
	struct event *ev;
	struct event_list *activeq = NULL;
	int i;
	short ncalls;
    
	// 从优先级低到高的顺序遍历, 如果低优先级队列不空, 则退出循环
	for (i = 0; i < base->nactivequeues; ++i) {
		if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
			activeq = base->activequeues[i];
			break;
		}
	}

	assert(activeq != NULL);
	// 从该优先级队列中开始进行调度
	for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
		// 如果该事件设置是永久有效, 则只是将该事件从就绪队列中删除, 并没有从 event_loop 中删除
		// 否则删除该事件
		if (ev->ev_events & EV_PERSIST)
			event_queue_remove(base, ev, EVLIST_ACTIVE);
		else
		      // 从所有队列中删除该事件
			event_del(ev);
		
		/* Allows deletes to work */
		ncalls = ev->ev_ncalls;
		ev->ev_pncalls = &ncalls;
		while (ncalls) {
			ncalls--;
			ev->ev_ncalls = ncalls;
			(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
			if (event_gotsig || base->event_break)
				return;
		}
	}
}
  1. 从优先级队列头部(也就是activequeues[0])开始循环, 只要该优先级队列不为空, 就退出循环, 执行下面的步骤.
  2. 从优先级队列中一个个取出就绪事件, 如果是永久事件则只从就绪队列中删除, 否则直接从所有队列中删除该事件
  3. 接着根据注册事件设置的次数, 调用多少次的回调函数.

思路其实很容易理解. 但这里有一点需要提醒, 因为每次激活都是从优先级为 0 的队列寻找, 一旦找到不为空的就会退出, 所以可能数值越大的就可能会被饿死. 能看出来, 数值越小其实优先级越高.

总结

如果你现在对libevent有了一定的认识后, 相信分析激活功能应该已经很轻松了才是.

  • 高优先级(数值大的)可能会被饿死.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值