event_base回调解析

本文详细探讨了libevent库中event_dispatch、event_base_loop和evsel等核心函数的作用,特别是如何通过evsel->dispatch进行事件调度。文章还介绍了libevent是如何通过全局静态数组eventops来决定使用哪种事件模型(如epoll、kqueue等),并最终实现了异步IO的高效处理。

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

刨根问底,了解libevent如何实现异步IO。
从后往前研究,先看event_dispatch干啥了
event_dispatch的实现
int  event_base_dispatch(struct event_base *event_base)
{
 return (event_base_loop(event_base, 0));   //唯一的操作是调用event_base_loop
}
继续看,
int
event_base_loop(struct event_base *base, int flags)
{
 const struct eventop *evsel = base->evsel;
。。。。
 while (!done) {
。。。。
res = evsel->dispatch(base, tv_p);   //最关键的部分,既然evsel是base的成员。接着看evsel和dispatch怎么来的,转到event_base_new
 。。。。。
if (N_ACTIVE_CALLBACKS(base))    //检查是否有活动的事件
{
   int n = event_process_active(base);     //处理活动的事件,调用事件回调函数。
   if ((flags & EVLOOP_ONCE)
       && N_ACTIVE_CALLBACKS(base) == 0
       && n != 0)
    done = 1;
  } else if (flags & EVLOOP_NONBLOCK)
   done = 1;
。。。。。

struct event_base  *event_base_new(void)
{
 struct event_base *base = NULL;
 struct event_config *cfg = event_config_new();
 if (cfg)
 {
  base = event_base_new_with_config(cfg);  //调用event_base_new_with_config创建event_base
  event_config_free(cfg);
 }
 return base;
}

struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
...........
//最关键的部分
 for (i = 0; eventops[i] && !base->evbase; i++)
 {
。。。。。。

  base->evsel = eventops[i];                    //直接给base->evsel赋值为 eventops[i],那么 eventops[i]从哪来呢。

  base->evbase = base->evsel->init(base);   //初始化
 }
。。。。。。。
}
//eventops是全局的静态数组
static const struct eventop *eventops[] = {
#ifdef _EVENT_HAVE_EVENT_PORTS
 &evportops,                                      //这些值都是外部变量,在相应的.c文件有定义
#endif
#ifdef _EVENT_HAVE_WORKING_KQUEUE
 &kqops,
#endif
#ifdef _EVENT_HAVE_EPOLL
 &epollops,                                          //epoll.c有定义,这就转到了epoll模型了
#endif
#ifdef _EVENT_HAVE_DEVPOLL
 &devpollops,
#endif
#ifdef _EVENT_HAVE_POLL
 &pollops,
#endif
#ifdef _EVENT_HAVE_SELECT
 &selectops,
#endif
#ifdef WIN32
 &win32ops,
#endif
 NULL
};

static int
epoll_dispatch(struct event_base *base, struct timeval *tv)
{
。。。。。
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);  //等待事件发生
。。。。
evmap_io_active(base, events[i].data.fd, ev | EV_ET);   //把产生的事件添加到活动事件队列
。。。

epoll还没仔细了解过,大概的思路就到这了


#ifndef ARDUINO_USB_MODE #error This ESP32 SoC has no Native USB interface #elif ARDUINO_USB_MODE == 1 //host模式 // 修复后的打印机控制代码 #include "USB.h" #include "USBPrinter.h" USBPrinter printer; /** * @brief USB打印机事件回调函数 */ static void usbPrinterEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (event_base == ARDUINO_USB_PRINTER_EVENTS) { switch (event_id) { case ARDUINO_USB_PRINTER_CONNECTED_EVENT: Serial.println("PRINTER CONNECTED"); printer.setTimeout(5000); // 5秒超时 break; case ARDUINO_USB_PRINTER_DISCONNECTED_EVENT: Serial.println("PRINTER DISCONNECTED"); break; case ARDUINO_USB_PRINTER_ERROR_EVENT: Serial.println("PRINTER ERROR"); break; case ARDUINO_USB_PRINTER_DATA_SENT_EVENT: Serial.println("DATA SENT TO PRINTER"); break; default: break; } } } void setup() { Serial.begin(115200); // 初始化USB主机 USB.begin(); // 注册打印机事件回调 printer.onEvent(usbPrinterEventCallback); Serial.println("Waiting for USB printer..."); } void loop() { static uint32_t lastPrint = 0; // 每5秒发送一次打印任务 if (millis() - lastPrint > 5000 && printer.connected()) { lastPrint = millis(); Serial.println("Sending print job..."); // 打印机初始化序列(ESC/POS示例) uint8_t initSeq[] = {0x1B, 0x40}; // 复位打印机 // 格式化打印内容 String printData = "\n=== ESP32 Printer Test ===\n"; printData += "Timestamp: " + String(millis()) + "\n\n"; // 发送打印数据 printer.sendData(initSeq, sizeof(initSeq)); // 发送初始化命令 printer.print(printData); // 发送文本内容 // 切纸命令(ESC/POS) uint8_t cutCmd[] = {0x1D, 0x56, 0x41, 0x10}; printer.sendData(cutCmd, sizeof(cutCmd)); } // 处理USB事件 USB.task(); } #else // 设备模式 - 保留原始CDC代码 #include "USB.h" #if !ARDUINO_USB_CDC_ON_BOOT USBCDC USBSerial; #endif static void usbEventCallback(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { // 原始事件回调代码保持不变... } void setup() { // 原始设备模式setup代码保持不变... } void loop() { // 原始设备模式loop代码保持不变... } #endif /* ARDUINO_USB_MODE */ 这个程序无法驱动打印机,优化一下
最新发布
08-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值