2012年10月31日星期三

libevent源码走读

libevent响应事件(文件描述符可读/可写、超时、信号),调用特定函数进行处理,libevent中主要有以下几个概念:

  1. 事件多路分发机制(event demultiplexer),即epoll、kqueue、select等
  2. 事件源,在指定的文件描述符上注册关心的事件,如I/O读写、定时、信号事件
  3. 事件处理器(event handler),事件触发时被调用
  4. 反应器(reactor),事件管理接口,注册事件后进入循环,事件就绪时调用事件处理函数


libevent中主要的几个接口:

  • event_init:初始化libevent库,生成event_base实例
  • event_set:初始化事件event,设置回调函数和关注的事件
  • event_base_set:设置event从属的event_base,即指明event要注册到哪个event_base上
  • event_add:正式添加事件
  • event_base_dispatch:程序进入无限循环,等待就绪事件


以下是上面各个函数的具体实现(基于libevent-2.0.20-stable版本)。

event_init函数:调用event_base_new_with_config,该函数进行事件多路分发机制选择。epoll、kqueue、select等多种事件多路分发机制被存放在eventops数组中,从该数组下标0开始选择,将选好的事件多路分发机制存放在evsel字段中。之后调用evsel->init,该接口函数最终调用对应事件多路分发机制的初始化函数,如epoll对应的是epoll_create。

event_set函数:调用event_assign,event_assign函数中,填充event结构中的文件描述符、事件类型、事件处理函数等字段。

event_base_set函数:简单地设定event结构中的ev_base字段为指定值。

event_add函数:调用event_add_internal,该函数中,根据不同的事件类型,调用不同函数处理,对于I/O,调用evmap_io_add;对于signal,调用evmap_signal_add。之后调用event_queue_insert,将事件加入激活事件队列。

在evmap_io_add和evmap_signal_add中,均会调用evsel->add,其作用就是调用某个具体事件多路分发机制的接口函数,完成事件添加。例如对应于epoll的add函数就是epoll_nochangelist_add,该函数调用epoll_apply_one_change,epoll_apply_one_change调用epoll_ctl进行事件注册。

event_base_dispatch函数:调用event_base_loop,该函数调用evsel->dispatch,即事件多路分发机制注册的dispatch函数,对应于epoll就是epoll_dispatch,epoll_dispatch调用epoll_wait,调用event_set函数时设定了监听的文件描述符,epoll_wait在此文件描述符上等待I/O事件发生。

Have fun!

没有评论:

发表评论