第八章第五节 event_add函数
event_add函数
创建一个event对象的函数为将event_new封装后的函数evsignal_new、evtimer_new等;event_new的实现比较简单,为event对象分配内存并初始化其部分成员。
创建了event对象后,应用程序调用event_add函数将其添加到注册事件队列中,并将相应的事件注册到事件多路分发器上。
event_add函数在event.c文件中实现,主要调用内部函数event_add_nolock_,外加调用前后两次加锁。
关于函数event_add_nolock_的分析详见代码清单12-3。
其中调用了几个重要的函数。
- evmap_io_add:将I/O事件添加到事件多路分发器中,并将对应的事件处理器添加到I/O事件队列中,同时建立I/O事件与I/O事件队列之间的映射关系;
- evmap_signal_add:将信号事件添加到事件多路分发器中,并将对应的事件处理器添加到信号事件队列中,同时建立信号事件与信号事件队列之间的映射关系;
- event_queue_insert:将事件处理器添加到各种事件队列中,即:将I/O事件处理器与信号事件处理器插入注册事件队列;将定时器插入通用定时器队列或时间堆;将被激活的事件处理器添加到活动事件队列中;
向事件多路分发器注册事件
本节具体介绍evmap_io_add与evmap_signal_add这两个函数。在此之前,先介绍要用到的重要的数据结构。这部分详见代码清单12-5。
eventop结构体
eventop结构体封装了I/O复用机制必要的一些操作,如注册事件、等待事件等。它为event_base支持的所有后端I/O复用机制提供了统一的接口。
1 | /* |
fdinfo_len
有的I/O复用机制需要为每个I/O事件队列与信号事件队列分配额外的内存,以避免同一个文件描述符被重复插入I/O复用机制的事件表中。于是在evmap_io_add/del在调用eventop的add/del方法时,将这段内存的起始地址作为第五个参数传递给add/del方法,fdinfo_len则用来指定这段内存的长度。
I/O复用技术的优先级
event ports > kqueue > epoll > /dev/poll > poll > select。
可见,在Linux下libevent默认选择epoll I/O复用技术。