libevent(7)libevent中的事件event

文章介绍了Libevent库中事件的4种状态:initialized、pending、active和persistent,详细说明了状态间的转换,并通过两个C++示例展示了如何使用libevent处理SIGINT和SIGTERM信号事件,以及在事件处理后如何维持或改变事件状态。

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

一、事件状态

libevent有4种事件状态,分别是: initialized、pending、active、persistent。这4种状态的转换关系如下:

1、已初始化(initialized):对应图中的non-pending状态,表示事件已经新建完成,但是还未添加到了libevent 队列中。有 4 种方法可以让事件跳转到此状态:

(1)调用 event_new 函数,返回一个事件对象,或调用 event_assign 赋值一个事件对象。

struct event *event_new(
    struct event_base *, evutil_socket_t, short, event_callback_fn, void *);

int event_assign(struct event *, 
    struct event_base *, evutil_socket_t, short, event_callback_fn, void *);

// 回调函数指针定义
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);

(2)pinding 状态的事件调用event_del函数后。

(3)active 状态的事件调用完成(即执行完事件回调函数),若没有定义持久化。

2、待决(pending):此状态表示事件已经位于libevent 队列中,可以随时准备执行。有 4 种方法可以让事件跳转到此状态:

(1)调用 event_add 之后。

(2)active 状态的事件调用完成(即执行完事件回调函数),若定义为持久化。

3、激活(active):此状态表示事件正在执行中,也包括超时事件。这是由 libevent 进行调度的,用户也可以手动调用 event_active 函数让事件转为此状态。

4、持久的(persistent):

(1)若定义为持久化,事件完成后状态会由 active 变为 pending ,可仍由 libevent 调用,不用做其他操作;

(2)若未定义为持久化,则表示事件完成后状态会由 active 变为 non-pending ,即初始化状态(initialized)。此时需要再次调用 event_add 函数,将事件变为 pending 状态,事件才会再次被执行。

二、例子

1、下面我们来看一个完整的例子 test_signal.cpp:


#include <iostream>
#include <string.h>
#include <signal.h>
#include <event2/event.h>
#include <event2/listener.h>

#define PORT 5001

using namespace std;

//socket 文件描述符
//which 事件类型
//arg 传递的参数 
static void Ctrl_C(int socket, short which, void* arg){
    cout<<"Ctrl_C"<<endl;
}

int main()
{   
    //创建libevent上下文
    event_base* base = event_base_new();
    if (base) {
        cout<<"event_base_new success!"<<endl;
    }

	//添加ctrl +c信号事件,处于no_pending状态
	event *csig = evsignal_new(base, SIGINT, Ctrl_C, base);
	if(!csig){
	    cerr<<"evsignal_new failed!"<<endl;
		return -1;
	}

	//添加事件到pending
	if(event_add(csig, 0) != 0){
	    cerr <<"event_add failed!"<< endl;
		return -1;
	}
	
    //事件分发处理
    if (base) {
        event_base_dispatch(base);
    }
	
    if (csig) {
	    event_free(csig);
	}
	
    if (base) {
        event_base_free(base);
    }

    return 0;
}

运行结果如下:

2、下面我们把这个例子再深化一下,添加下其他event:


#include <iostream>
#include <string.h>
#include <signal.h>
#include <event2/event.h>
#include <event2/listener.h>

#define PORT 5001

using namespace std;

//socket 文件描述符
//which 事件类型
//arg 传递的参数 
static void Ctrl_C(int socket, short which, void* arg){
    cout<<"Ctrl_C"<<endl;
}

static void Kill(int socket, short which, void* arg){
    cout<<"Kill"<<endl;
	
	//加上下面这段代码后,event又变被重新pending
	event* ev = (event*)arg;
	if(!evsignal_pending(ev, NULL)){
	    event_del(ev);
		event_add(ev, NULL);
	}
}

int main()
{   
    //创建libevent上下文
    event_base* base = event_base_new();
    if (base) {
        cout<<"event_base_new success!"<<endl;
    }

	//添加ctrl +c信号事件,处于no_pending状态
	//evsignal_new隐藏的状态: EV_SIGNAL|EV_PERSIST
	event *csig = evsignal_new(base, SIGINT, Ctrl_C, base);
	if(!csig){
	    cerr<<"evsignal_new csig failed!"<<endl;
		return -1;
	}

	//添加事件到pending
	if(event_add(csig, 0) != 0){
	    cerr <<"event_add csig failed!"<< endl;
		return -1;
	}
	
	//添加kill信号
	//EV_SIGNAL: 没有添加EV_PERSIST,表面当前event为非持久化事件,只能执行1次
	//event_self_cbarg(): 传递当前的event
	event *ksig = event_new(base, SIGTERM, EV_SIGNAL, Kill, event_self_cbarg());
	if(!ksig){
	    cerr<<"event_new ksig failed!"<<endl;
		return -1;
	}

	//添加事件到pending
	if(event_add(ksig, 0) != 0){
	    cerr <<"event_add ksig failed!"<< endl;
		return -1;
	}
	
    //事件分发处理
    if (base) {
        event_base_dispatch(base);
    }
	
    if (csig) {
	    event_free(csig);
	}
	
    if (base) {
        event_base_free(base);
    }

    return 0;
}

执行结果如下:

参考:

Libevent 学习四:事件状态和事件处理
https://blog.youkuaiyun.com/myw31415926/article/details/127372808

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值