libevent的优点
- 使用了Reator模式,响应快,高性能,不会为单个时间阻塞
- 专注于网络
- 跨平台
- 支持I/O多路复用技术
- 支持I/O,定时器和信号
Reator
Reator不同于普通的函数调用
普通的函数调用流程是
程序调用函数->函数执行->程序等待函数执行完毕(期间有可能会阻塞,等待某个事件来临)->程序继续执行
而Reator模式不一样
程序先将事件和函数注册到Reator反应堆上->Reator等待事件发生调用函数->函数执行完毕(这个时候函数不会等待,因为所以需要的条件都已经有了)->程序继续执行
Libevent
库的核心 event
Libevent 是基于事件驱动(event-driven)的,从名字也可以看到 event 是整个库的核心。
event 就是 Reactor 框架中的事件处理程序组件
- ev_events: event关注的事件类型,它可以是以下3种类型:
I/O事件: EV_WRITE和EV_READ
定时事件: EV_TIMEOUT
信号: EV_SIGNAL
辅助选项: EV_PERSIST,表明是一个永久事件 - ev_next是双向链表节点指针;它是 libevent对事件的管理时使用到的字段。
libevent 使用双向链表保存所有注册的 I/O事件, ev_next 就是该 I/O 事件在链表中的位置;称此链表为"已注册事件链表"; - ev_base 该事件所属的反应堆实例,这是一个 event_base 结构体
- ev_fd,对于 I/O 事件,是绑定的文件描述符
- ev_callback, event 的回调函数,被 ev_base 调用,执行事件处理程序,这是一个函数指针
- eb_flags: libevent 用于标记 event 信息的字段,表明其当前的状态,可能的值有:
#define EVLIST_TIMEOUT | 0x01 // event在time堆中 |
#define EVLIST_INSERTED 0x02 // event在已注册事件链表中 | |
#define EVLIST_SIGNAL | 0x04 // 未见使用 |
#define EVLIST_INTERNAL 0x10 // 内部使用标记 | |
#define EVLIST_INIT | 0x80 // event 已被初始化 |
- ev_ncalls:事件就绪执行时,调用 ev_callback 的次数,通常为 1;
对event的管理
每次当有事件 event 转变为就绪状态时, libevent 就会把它移入到 active event list[priority]中,其中 priority 是 event 的优先级;
int event_add(struct event *ev, const struct timeval *tv)
先找到要注册的event_base
查看事件ev在不在"已注册链表"和"就绪链表"里 如果不在就调用该event_base的I/O复用(epoll)注册事件 并且将ev插入到"已注册链表"里
多线程
Libevent本身不是多线程安全的
多线程环境下需要多个Reator实例