2025年5月28日 星期三 乙巳(蛇)年 三月初一 设为首页 加入收藏
rss
您当前的位置:首页 > 电子 > 单片机

MT7688学习笔记(8)——使用libevent创建定时器

时间:03-02来源:作者:点击数:58

一、简介

libevent 默认情况下是单线程的,可以配置成多线程,每个线程有且只有一个event_base,对应一个struct event_base结构体以及附于其上的事件管理器,用来调度托管给它的一系列event,可以和操作系统的进程管理类比。当一个事件发生后,event_base会在合适的时间,不一定是立即去调用绑定在这个事件上的函数,直到这个函数执行完,再去调度其他的事件。

event_base内部有一个循环,循环阻塞在epoll等系统调用上,直到有一个/一些时间发生,然后去处理这些事件。当然,这些事件要被绑定在这个event_base上,每个事件对应一个struct event,可以是监听一个fd或者信号量之类的,struct event使用event_new来创建和绑定,使用event_add来将event绑定到event_base中。

libevent 中,用最小堆(min-heap)来管理所有定时器。

root node 就是最近即将触发的 timer event。node value 就是 timer 触发的时间(秒)。

二、流程

1、初始化libevent

2、设置事件

3、添加事件

4、进入循环

2.1 初始化libevent

首先初始化libevent库,并保存返回的指针

struct event_base *base = event_base_new();

这一步相当于初始化一个Reactor实例;在初始化libevent后,就可以注册事件了。

2.2 设置事件

2.2.1 定义两个结构体

分别代表事件和定时器值

struct event ev; //定时器事件

struct timeval timeout; //定时器值

2.2.2 将事件和event_base绑定

event_assgin()函数

原型:

int event_assign(struct event *event, struct event_base *base, evutil_socket_t fd, short what, void (*callback)(evutil_socket_t, short, void *), void *arg);

用法:

event_assign(&ev, base, -1, flags, cb_func, (void*)&ev);

在创建定时器事件时,使用的是struct event ev,也可以用event_new函数动态分配,这样就不需要event_assign函数了。

event_new()函数

原型:

struct event *event_new(struct event_base *base, evutil_socket_t fd, short what, event_callback_fn cb, void *arg);

用法:

struct event *ev = event_new(base, -1, what, cb_func, arg);

其中,what事件类型及属性如下:

#define EV_TIMEOUT 0x01 // 定时事件

#define EV_READ 0x02 // I/O事件

#define EV_WRITE 0x04 // I/O事件

#define EV_SIGNAL 0x08 // 信号

#define EV_PERSIST 0x10 // 永久事件

#define EV_ET 0x20 // 边沿触发

回调函数

void cb_func(evutil_socket_t fd, short what, void *arg);

在分配后可以用event_free来释放

event_free(ev);

2.3 添加事件

虽然已经初始化了事件,但是该事件并不会被触发,原因在于我们并没有激活该事件。

event_add()函数提供了激活事件的功能。

event_add()函数

原型:

int event_add(struct event *ev, const struct timeval *tv);

用法:

event_add(ev, &timeout)

如果是一个(non-pending)未注册ev,调用event_add函数会注册该事件(变为pending状态)。如果是一个(pending)注册过的ev,调用该函数会在tv时间后重新注册该事件。成功返回0,失败返回-1。

2.4 进入循环

程序进入无限循环,等待就绪事件并执行事件处理

event_base_dispatch()函数

原型:

int event_base_dispatch(struct event_base *base);

用法:

event_base_dispatch(base);

还可以使用event_base_loop()函数。

三、头文件

  • #include <event2/event.h>

四、例子

  • void mian(void)
  • {
  • struct event_base *base = event_base_new();
  • CreateTimer(base, 2, 0, true, DoCallBack, nullptr);
  • event_base_dispatch(base);
  • event_base_free(base);
  • }
  • /**
  • @brief 创建定时器
  • @param base 指向event_base类型的指针
  • @param sec 秒数
  • @param usec 微秒数
  • @param repeat 是否重复
  • @param func() 回调函数
  • @param arg 指向传递给这个回调函数来使用的参数
  • @return true - 成功;false - 失败
  • */
  • bool CreateTimer(event_base *base,int sec,int usec,bool repeat,void (*func)(evutil_socket_t ,short ,void *),void *arg)
  • {
  • if (base == nullptr)
  • {
  • return false;
  • }
  • if ((sec == 0) && (usec == 0))
  • {
  • return false;
  • }
  • struct timeval timeout;
  • /* 初始化事件
  • * base:event_base类型,event_base_new的返回值
  • * fd:监听的fd,listen的fd。 定时事件fd为 -1
  • * what:事件的类型及属性 EV_PERSIST - 永久事件,使得event_add永久生效,直到event_del调用
  • * cb:绑定的回调函数
  • * arg:给回调函数的参数
  • */
  • struct event *ev = event_new(base, -1, repeat?EV_PERSIST:0, func, arg);
  • if (ev)
  • {
  • timeout.tv_sec = sec; // 秒
  • timeout.tv_usec = usec; // 微秒
  • /* 激活事件
  • * 如果是一个未注册'ev',调用'event_add'函数会注册该事件
  • * 如果是一个注册过的'ev',调用该函数会在tv时间后重新注册该事件
  • */
  • event_add(ev, &timeout);
  • return true;
  • }
  • return false;
  • }

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门