libevent学习笔记六:libevent核心事件event

前面对reactor模式、事件处理流程、libevent源代码结构等有了高层的认识后,接下来将详细介绍libevent的核心结构event,以及libevent对event的管理。

1 、libevent的核心-event

Libevent是基于事件驱动(event-driven驱动)的,单从名字也可以看到event是整个库的核心。event就是Reactor框架中的事件处理程序组件;它提供了函数接口,供Reactor在事件发生时调用,以执行相应的事件处理,通常它会绑定一个有效的句柄。
首先给出event结构体的声明,它位于event.h文件中:

 struct event {TAILQ_ENTRY (event) ev_next;TAILQ_ENTRY (event) ev_active_next;TAILQ_ENTRY (event) ev_signal_next;unsigned int min_heap_idx; /* for managing timeouts */struct event_base *ev_base;int ev_fd;short ev_events;short ev_ncalls;short *ev_pncalls; /* Allows deletes in callback */struct timeval ev_timeout;int ev_pri;  /* smaller numbers are higher priority */void (*ev_callback)(int, short, void *arg);void *ev_arg;int ev_res;  /* result passed to event callback */int ev_flags;};

下面逐项简单解释一下结构体中各字段的含义。
1)ev_events:event关注的事件类型,它可以是以下3种类型:
    I/O事件: EV_WRITE和EV_READ
    定时事件:EV_TIMEOUT
    信号:    EV_SIGNAL
    辅助选项:EV_PERSIST,表明是一个永久事件
  Libevent中的定义为:

  #define EV_TIMEOUT 0x01#define EV_READ  0x02#define EV_WRITE 0x04#define EV_SIGNAL 0x08#define EV_PERSIST 0x10 /* Persistant event */

可以看出事件类型可以使用“|”运算符进行组合,但需要注意和说明的是,信号和I/O事件不能同时设置;libevent使用event结构体将这3种事件的处理统一起来;

2)链表节点指针

ev_next,ev_active_next和ev_signal_next都是双向链表节点指针;它们是libevent对不同事件类型和在不同的时间状态时期,对事件的管理时使用到的字段。libevent使用双向链表保存所有注册的I/O和Signal事件,

ev_next就是该I/O事件在链表中的位置;称此链表为“已注册事件链表”;

ev_signal_next就是signal事件在signal事件链表中的位置;

ev_active_next:libevent将所有的激活事件放入到链表active list中,然后遍历active list执行调度,ev_active_next就指明了event在active list中的位置;

3)min_heap_idx和ev_timeout,如果是timeout事件,它们是event在小根堆中的索引和超时值,libevent使用小根堆来管理定时事件。
4)ev_base该事件所属的反应堆实例,这是一个event_base结构体;

5)ev_fd,对于I/O事件,是绑定的文件描述符;对于signal事件,是绑定的信号;

6)ev_callback,event的回调函数,被ev_base调用,执行事件处理程序,这是一个函数指针,原型为:

  void (*ev_callback)(int fd, short events, void *arg)

其中参数fd对应于ev_fd;events对应于ev_events;arg对应于ev_arg;

7)ev_arg:void*,表明可以是任意类型的数据,在设置event时指定;

8)eb_flags:libevent用于标记event信息的字段,表明其当前的状态,可能的值有:

 #define EVLIST_TIMEOUT 0x01 // event在time堆中#define EVLIST_INSERTED 0x02 // event在已注册事件链表中#define EVLIST_SIGNAL 0x04 // 未见使用#define EVLIST_ACTIVE 0x08 // event在激活链表中#define EVLIST_INTERNAL 0x10 // 内部使用标记#define EVLIST_INIT     0x80 // event已被初始化

9)ev_ncalls:事件就绪执行时,调用ev_callback的次数,通常为1;

10)ev_pncalls:指针,通常指向ev_ncalls或者为NULL;

11)ev_res:记录了当前激活事件的类型;

2 、libevent对event的管理

从event结构体中的3个链表节点指针和一个堆索引出发进行分析跟踪,总体上也能摸清ibevent对event的管理方法的脉络了,参照下面的示意图,可以对管理的方法和思路进一步的深入理解:

每次当有事件event转变为就绪状态时,libevent就会把它移入到active event list[priority]中,其中priority是event的优先级;

接着libevent会根据自己的调度策略选择就绪事件,调用其cb_callback()函数执行事件处理;并根据就绪的句柄和事件类型填充cb_callback函数的参数。

3 、事件设置的接口函数

要向libevent添加一个事件,需要首先设置event对象,这通过调用libevent提供的函数有:event_set(), event_base_set(), event_priority_set()等来完成;下面分别进行讲解。

3.1 event_set

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

1.设置事件ev绑定的文件描述符或者信号,对于定时事件,设为-1即可;
2.设置事件类型,比如EV_READ|EV_PERSIST, EV_WRITE, EV_SIGNAL等;
3.设置事件的回调函数以及参数arg;
4.初始化其它字段,比如缺省的event_base和优先级;

3.2 event_base_set

  int event_base_set(struct event_base *base, struct event *ev)

设置event ev将要注册到的event_base;
libevent有一个全局event_base指针current_base,默认情况下事件ev将被注册到current_base上,使用该函数可以指定不同的event_base;
如果一个进程中存在多个libevent实例,则必须要调用该函数为event设置不同的event_base;

3.3 event_priority_set

  int event_priority_set(struct event *ev, int pri)

设置event ev的优先级,没什么可说的,注意的一点就是:当ev正处于就绪状态时,不能设置,返回-1。

4 、总结

本文讲述了libevent的核心event结构,以及libevent支持的事件类型和libevent对event的管理模型;接下来将会介绍libevent的事件处理框架,以及其中使用的重要的结构体event_base,继续深入探索Libevent结构。

libevent学习笔记六:libevent核心事件event相关推荐

  1. Java之GUI编程学习笔记六 —— AWT相关(画笔paint、鼠标监听事件、模拟画图工具)

    Java之GUI编程学习笔记六 -- AWT相关(画笔paint) 参考教程B站狂神https://www.bilibili.com/video/BV1DJ411B75F 了解paint Frame自 ...

  2. Windows事件等待学习笔记(四)—— 事件信号量互斥体

    Windows事件等待学习笔记(四)-- 事件&信号量&互斥体 要点回顾 事件 实验:验证SignalState 第一步:编译并运行以下代码 第二步:观察结果 第三步:修改代码并执行 ...

  3. Libevent 学习一:Libevent 源码编译

    文章目录 Libevent 学习一:Libevent 源码编译 Libevent Windows 编译 Windows 编译环境 安装 Visual Studio Community 2015 安装 ...

  4. Vue.js 学习笔记 五 常用的事件修饰符

    介绍几个常用的事件修饰符 直接上代码 <div id="divApp"><div class="divColor" v-on:click=&q ...

  5. JavaScript学习笔记(三)---事件、正则表达式、ES6、运动

    JavaScript学习笔记(三)---事件.正则表达式.ES6.运动 27.insertbefore 28.滚动条及事件 29.事件及事件对象 30.鼠标事件对象的属性 31.案例:图片随鼠标移动 ...

  6. Python学习笔记六——画小猪佩奇

    目录 Python学习笔记六--画小猪佩奇 画布 画笔 属性设置 操纵命令 运动命令 画笔控制命令 全局控制命令 其他命令 Python学习笔记六--画小猪佩奇 使用Python的turtle库可以绘 ...

  7. oracle job enq tx,【学习笔记】Oracle等待事件 enq:TX–allocate ITL entry产生原因和解决办法...

    天萃荷净 运维DBA反映Oracle数据库出现enq:TX–allocate ITL entry等待事件,结合案例分析该等待事件产生原因和解决办法 今天在分析一份awr中发现了较为明显的enq: TX ...

  8. Ethernet/IP 学习笔记六

    Ethernet/IP 学习笔记六 EtherNet/IP defines two primary types of communications: explicit and implicit (Ta ...

  9. 吴恩达《机器学习》学习笔记六——过拟合与正则化

    吴恩达<机器学习>学习笔记六--过拟合与正则化 一. 过拟合问题 1.线性回归过拟合问题 2.逻辑回归过拟合问题 3.过拟合的解决 二. 正则化后的代价函数 1.正则化思想 2.实际使用的 ...

最新文章

  1. Boost:circular_buffer作为边界缓冲区的基础容器
  2. 编译linux内核时出错
  3. es6 数组合并_对比 ES5,学习 ES6(一)
  4. ES5-11原型与原型链深入、对象继承
  5. C# 强大的新特性 Source Generator
  6. java el ognl_EL和OGNL表达式的区分
  7. [转载] 手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis
  8. java 多线程学习
  9. 如何在关闭ssh连接的情况下,让进程继续运行?
  10. Docker系列教程26-Docker Compose控制服务启动顺序
  11. linux系统调用使用方法,Linux系统的使用以及系统调用的开发方法OS.ppt
  12. 日常笔记系列:java汉字判断
  13. 首页css命名,常用的CSS命名规则
  14. 重要更新丨完成前端重构,KubeOperator开源容器平台v3.7.0发布
  15. 2014淘宝钻石展位新客户考试
  16. web自动化测试-第五讲: 三大切换
  17. 『团队协作的五大障碍』读书所得
  18. Java 无需解压直接读取ZIP压缩包里的文件及内容
  19. Google将推出Android手机版Voice应用程序
  20. Git提交代码到新仓库(--mirror)

热门文章

  1. 汉帝国总裁刘彻管理实录
  2. Linux | 基础指令
  3. 值得一读的20个经典小故事(生命的价值)
  4. CSS 实现鼠标hover 展示内容
  5. Ubuntu下安装deb包的命令总结
  6. c语言指针没学可以学java_20165312 C语言基础调查和JAVA学习展望
  7. 【如何用C++编程制作一个简单的游戏引擎】
  8. springboot操作以太坊(eth),使用web3j,转账等
  9. MP4V2封装h265
  10. 陆奇最新演讲实录:我的大模型世界观