libevent 源码学习三 —— 基本使用场景和事件流程
基本应用场景——libevent 基本流程
eg: 使用 libevent 设置定时器。
1. 初始化 libevent 库,并保存返回的指针
struct event_base* base = event_init(); // 初始化后,就可以注册事件了
2. 初始化事件 event,设置回调函数和关注事件
evtimer_set(&ev, timer_cb, NULL); 等价于调用 event_set(&ev, -1, 0, timer_cb,NULL);
event_set 的函数原型是 void event_set(struct event* ev, int fd, short event, void(*cb)(int, short,void*), void *arg)
ev : 执行要初始化的对象
fd :文件描述符,或者说是句柄
event :该 fd 上关注的事件类型, EV_READ, EV_WRITE, EV_SIGNAL
cb : 函数指针,回调函数。fd 上的事件发生时,调用该函数执行处理,它有3个参数,调用时由event_base 负责传入,按顺序,实际上就是event_set 的 fd event arg
arg : 传递给 cb 函数指针的参数
3 设置 event 从属的 event_base
event_base_set(base, & ev); // 指明 event 要注册到哪个event_base 实例上
4 正式的添加事件
event_add(&ev, timeout) // timeout 是定时值
5 程序进入循环等待,等待就绪事件病执行事件处理
event_base_dispatch(base);
6 实例代码:
struct event ev;
struct timeval tv;
void time_cb(int fd, short event, void* arg){
printf("time wakeup/n");
event_add(&ev, &tv);
}
int main(){
struct event_base *base = event_init();
tv.tv_sec = 10;
tv.tv_usec = 0;
evtimer_set(&ev, time_cb, NULL);
event_add(&ev, &tv);
event_base_dispatch(base);
}
7 事件处理流程
a 首先应用程序准备病初始化 event,是设置好事件类型和回调函数
b 想libevent 添加该事件 event, 对于定时事件, libevent 使用一个小堆根管理,Signal 和 I/O 事件,libevent 将其放入等待链表中
c 程序调用 event_base_dispatch() 系列函数进入无线循环,等待事件。libevent 将所有就绪的事件,放入到激活链表中
d 然后对激活链表中的事件, 调用事件的回调函数执行事件处理