libevent源码

1) 源码结构

Libevent 的源代码虽然都在一层文件夹下面,但是其代码分类还是相当清晰的,主要可分为头文件、内部使用的头文件、辅助功能函数、日志、libevent 框架、对系统 I/O 多路复用机制的封装、信号管理、定时事件管理、缓冲区管理、基本数据结构和基于 libevent的两个实用库等几个部分,有些部分可能就是一个源文件。
(1)头文件
主要就是 event.h:事件宏定义、接口函数声明,主要结构体 event 的声明;
(2)内部头文件
xxx-internal.h:内部数据结构和函数,对外不可见,以达到信息隐藏的目的;
(3)libevent框架
event.c:event 整体框架的代码实现;
(4)对系统 I/O多路复用机制的封装
epoll.c:对 epoll 的封装;
select.c:对 select 的封装;
devpoll.c:对 dev/poll 的封装;
kqueue.c:对kqueue 的封装;
(5)定时事件管理
min-heap.h:其实就是一个以时间作为 key的小根堆结构;
(6)信号管理
signal.c:对信号事件的处理;
(7)辅助功能函数
evutil.h  和 evutil.c:一些辅助功能函数,包括创建 socket pair和一些时间操作函数:加、减和比较等。
(8)日志
log.h和 log.c:log 日志函数
(9)缓冲区管理
evbuffer.c 和buffer.c:libevent 对缓冲区的封装;
(10)基本数据结构
compat/sys 下的两个源文件: queue.h是 libevent 基本数据结构的实现,包括链表,双向链表,队列等;_libevent_time.h:一些用于时间操作的结构体定义、函数和宏定义;
(11)实用网络库
     http 和evdns:是基于 libevent 实现的http 服务器和异步 dns 查询库;

 

 

2) mem$d是如何使用libevent

The tree was showed that how libevent was used in mem$d, also it is a scenario that how to use libevent in multi-thread, in mem$d, it uses main thread and worker threads mode, each thread has its own event base, doing its event loop to check the cared event. Each worker thread has a CQ, main thread will push task into CQ and send a notification to it, so the worker thread will get this notification, then start to process the task in CQ. The main thread use the round robin to select the work thread to do the task.

 

/* initialize main thread libevent instance */ main_base = event_init(); /* start up worker threads if MT mode */ thread_init(settings.num_threads, main_base); /* the type of threads[i] is LIBEVENT_THREAD */ -- setup_thread(&threads[i]); /* initial current thread own's event base */ -- me->base = event_init(); /* setup the notification event, the main thread will send a * message to current thread, tell it the task queue has task, * note that the event is persist event (don't remove from * register queue and fdset) */ -- event_set(&me->notify_event, me->notify_receive_fd, EV_READ | EV_PERSIST, thread_libevent_process, me); /* associate this event to event base */ -- event_base_set(me->base, &me->notify_event); /* register the event */ -- event_add(&me->notify_event, 0) /* create the worker pthread */ -- create_worker(worker_libevent, &threads[i]); -- pthread_create(&thread, &attr, func, arg) /* current worker pthread's event loop */ -- event_base_loop(me->base, 0); server_socket(settings.port, tcp_transport, portnumber_file) -- socket/bind/listen /* prepare the data structure struct conn *which representing a connection into memcached */ -- isten_conn_add = conn_new(sfd, conn_listening, EV_READ | EV_PERSIST, 1, transport, main_base))) /* initial event structure and set the event * base, event_flags is EV_READ | EV_PERSIST */ -- event_set(&c->event, sfd, event_flags, event_handler, (void *)c); -- drive_machine(c); /* when state is conn_listening, ony called from the main thread */ -- dispatch_conn_new(sfd, conn_new_cmd, EV_READ | EV_PERSIST, DATA_BUFFER_SIZE, tcp_transport); /* round robin select the worker thread, then * push the item into its CQ */ -- cq_push(thread->new_conn_queue, item); /* write one bit to notify the worker thread * which is doing event loop */ -- write(thread->notify_send_fd, "", 1); -- event_base_set(base, &c->event); /* register the listening fd in main base */ -- event_add(&c->event, 0); /* enter the main event loop */ event_base_loop(main_base, 0);

详细参考:http://wenku.baidu.com/view/89aba04d2b160b4e767fcff1.html

你可能感兴趣的:(source,Code)