libevent能够处理三种事件: I/O、信号、定时器。
涉及两个数据结构:
event,表示一个事件
event_base,管理所有事件
本文主要介绍event_base,结构如下:
struct event_base { const struct eventop *evsel; // backend void *evbase; const struct eventop *evsigsel; struct evsig_info sig; int event_count; // 事件总数 int event_count_active; // 活跃事件总数 struct event_list eventqueue; // 存储所有事件 struct event_io_map io; // 存储I/O事件 struct event_signal_map sigmap; // 存储信号事件 struct min_heap timeheap; // 存储定时器事件 struct event_list *activequeues; // 存储激活事件 int nactivequeues; // 激活队列个数 struct timeval event_tv; struct timeval tv_cache; void *th_base_lock; int is_notify_pending; evutil_socket_t th_notify_fd[2]; struct event th_notify; int (*th_notify_fn)(struct event_base *base); ... };
evsel主要描述libevent的底层实现机制,linux系统对应epoll。
/** Structure to define the backend of a given event_base. */ struct eventop { const char *name; void *(*init)(struct event_base *); int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo); int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo); int (*dispatch)(struct event_base *, struct timeval *); void (*dealloc)(struct event_base *); int need_reinit; enum event_method_feature features; size_t fdinfo_len; }; const struct eventop epollops = { "epoll", epoll_init, epoll_nochangelist_add, epoll_nochangelist_del, epoll_dispatch, epoll_dealloc, 1, /* need reinit */ EV_FEATURE_ET|EV_FEATURE_O1, 0 };
event_list是一个双向链表,min_heap是一个小根堆,而event_io_map结构有点复杂。
在linux系统,event_io_map就是event_signal_map,结构如下:
struct event_signal_map { void **entries; /* An array of evmap_io * or of evmap_signal */ int nentries; }; struct evmap_io { struct event_list events; ev_uint16_t nread; ev_uint16_t nwrite; }; struct evmap_signal { struct event_list events; };
一图胜千言:
可以看出,一个event_signal_map对应多个双向链表。同一个fd或signal的事件位于同一个链表中。
时间: 2024-10-08 17:11:04