总结
- tree.h中的RB_ENTRY用于存放EVLIST_TIMEOUT的event事件
- 延迟时间的处理函数
- EVLIST_ACTIVE状态:系统将所有待回调的函数放到activequeue队列中,并在loop中调用event_process_active来回调所有处于EVLIST_ACTIVE的事件
- select中实现signal的方法
event状态图

|
|
常用变量
全局队列
- static RB_HEAD(event_tree, event) timetree:以红黑树存储所有超时的event
- static struct event_list activequeue: 存储所有已响应待处理的event,signal和RW事件响应后自动转入该队列
- struct event_list signalqueue:存储所有signal事件未处理
- struct event_list eventqueue:存储所有READ|WRITE的event未处理
- static struct timeval event_tv: 保存系统当前时间
|
|
event结构体和状态
|
|
event(event.h和event.c)
- event_process_active: 对activequeue中所有的event调用ev_callback回调函数
- event_haveevents: int XXX(void)判断当前是否有事件
- event_set:
(struct event *ev, int fd, short events, void (*callback)(int, short, void *), void *arg)初始化事件ev_flags = EVLIST_INIT - event_pending:挂起事件
- event_add: 添加事件==添加到对应queue、设置flag、设置tv
- event_del: 删除时间
- event_active: 参数
(struct event *ev, int res, short ncalls)==加入avtive队列、设置ncalls执行次数、设定res - event_queue_remove:
(struct event *ev, int queue)将事件移除响应的queue队列 - event_queue_insert:
(struct event *ev, int queue)将事件加入响应的queue队列
|
|
time
数据结构
libevent将所有设置里EVLIST_TIMEOUT的event存放到一个event_tree结构体的timetree树中,同时创建以event_tree为节点类型的树结构的响应函数:
- event_tree结构体
- timetree:实际存储超时event的红黑树123456789101112131415struct { \struct type *rbe_left; /* left element */ \struct type *rbe_right; /* right element */ \struct type *rbe_parent; /* parent element */ \int rbe_color; /* node color */ \}// 使用tree.h的RB_HEAD结构创建以event_tree为名的结构体struct name { \struct type *rbh_root; /* root of the tree */ \}static RB_HEAD(event_tree, event) timetree;
相关函数
- timeout_next: 获取eventree中最小时间的tv用于dispatch中的tv参数
- timeout_correct: event.c中设有全局变量
event_tv保存当前时间,用于校验时间 - timeout_process: 处理所有超时的时间,并将其加入到active队列中
- timeout_insert:
(struct event *ev)将事件插入超时queue12345678910111213141516171819202122232425262728293031323334// off是event_tv与当前时间的差void timeout_correct(struct timeval *off){struct event *ev;/* We can modify the key element of the node without destroying* the key, beause we apply it to all in the right order.*/RB_FOREACH(ev, event_tree, &timetree)timersub(&ev->ev_timeout, off, &ev->ev_timeout);}void timeout_process(void){struct timeval now;struct event *ev, *next;gettimeofday(&now, NULL);for (ev = RB_MIN(event_tree, &timetree); ev; ev = next) {if (timercmp(&ev->ev_timeout, &now, >))break;next = RB_NEXT(event_tree, &timetree, ev);event_queue_remove(ev, EVLIST_TIMEOUT);/* delete this event from the I/O queues */event_del(ev);LOG_DBG((LOG_MISC, 60, "timeout_process: call %p",ev->ev_callback));event_active(ev, EV_TIMEOUT, 1);}}
signal相关的函数
- signal_deliver: 解除sop中的信号中断屏蔽
- signal_process: 将signalqueue中所有event转到event_queue中12345678910111213141516171819202122232425262728// event.c event_dispatch中int signal_deliver(void){//sigprocmask用于解除(SIG_UNBLOCK)进程中的信号中断屏蔽return (sigprocmask(SIG_UNBLOCK, &sop.evsigmask, NULL));/* XXX - pending signals handled here */}// event.c event_dispatch中void signal_process(void){struct event *ev;short ncalls;TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {ncalls = evsigcaught[EVENT_SIGNAL(ev)]; //#define EVENT_SIGNAL(ev) ev->ev_fdif (ncalls) {if (!(ev->ev_events & EV_PERSIST))event_del(ev);event_active(ev, EV_SIGNAL, ncalls); //ev->ev_ncalls = ncalls;//event_queue_insert(ev, EVLIST_ACTIVE);//将中断事件和中断次数放到event,并添加到activequeue}}memset(evsigcaught, 0, sizeof(evsigcaught));signal_caught = 0;}
select中实现signal的方法
libevent使用evsigcaught表示每次第i=fd的终端事件发生的次数
|
|