The core of libevent -event
Libevent is event-driven (event-driven), and from the name you can see that the event is the core of the entire library . The event is the Reactor component of the events handler in the framework, which provides a function interface for Reactor called when an event occurs to perform the appropriate event handling, usually it binds a valid handle.
The structure of the event in Event2/event_struct.h describes the struct event {tailq_entry (event) Ev_next; /* Add next event */tailq_entry Ev_active_next; /* Add the next Activity Event */tailq_entry (event) Ev_signal_next; /* Add the next signal *//*ev_next,ev_active_next and Ev_signal_next are both doubly linked list node pointers, which are the fields used by Libevent for different event types and for managing events at different times. Libevent uses a doubly linked list to hold all registered I/O and signal events, Ev_next is the position of the I/O event in the linked list, which is called the list of registered events; same Ev_signal_ Next is the position of the signal event in the Signal Event list, ev_active_next:libevent all the activation events into the list active lists, and then iterates through the active list execution schedule, ev_active_ Next indicates the position of the event in the active list; */unsigned int min_heap_idx; /* For managing timeouts represents the index of the event saved in the min_heap array */struct timeval ev_timeout; The timeout period used to hold events/*min_heap_idx and ev_timeout, if it is a timeout event, they are the index and time-out value of event in the small root heap, libevent use small Gan to manage timed events */struct Event_ Base *ev_base; /* This event belongs to the reactor instance, which is a event_base structural body */int ev_fd; /* For the I/O event, is the binding file descriptor, and for the signal event, is the binding signal */short ev_events; /*event is concerned about the type of event, which can be the following 3 types: I/O events: Ev_write and Ev_read timing events: Ev_timeout signal: ev_signal auxiliary options: Ev_persist, Indicates that it is a definition in the libevent of a permanent eventFor: #define EV_TIMEOUT 0x01 #define EV_READ 0x02 #define Ev_write 0x04 #define Ev_signal 0x08 #define Ev_persist 0x 10 you can see that the event type can use the ' | ' operator, it should be stated that the signal and I/O events cannot be set at the same time, and you can see that Libevent uses the event structure to unify the processing of these 3 events; */void *ev_arg; /* The parameter of the callback function, void*, indicates that it can be any type of data, specifying */void (*ev_callback) When setting event (int fd, short events, void *arg); The/*event callback function, called by Ev_base, executes the event handler, which is a function pointer where the parameter FD corresponds to ev_fd;events corresponding to the ev_events;arg corresponding to the Ev_arg*/int ev_pri; /* Smaller numbers is higher priority */short ev_ncalls; /* When the event is ready to execute, the number of calls to Ev_callback, usually 1*/short *ev_pncalls; /* Allows deletes in callback, pointer, usually pointing to ev_ncalls or for Null*/int ev_res; /* Result passed to event callback, recording the type of the current activation event */int ev_flags; /*libevent the field used to mark the event information, indicating its current state, the possible values are: #define EVLIST_TIMEOUT 0x01//event in the time heap #define evlist_inserted 0x02// Event in the Registered event List #define EVLIST_SIGNAL 0x04//Unused #define EVLIST_ACTIVE 0x08//event in the active list #define Evlist_int Ernal 0x10//Internal Use tag #define EVLIST_INIT 0x80//event has been initialized #define EVlist_timeout 0x01//event in the time heap #define evlist_inserted 0x02//event in the Registered event List #define Evlist_signal 0x04//not seen in use #d Efine evlist_active 0x08//event in the activation list #define EVLIST_INTERNAL 0x10//Internal Use tag #define EVLIST_INIT 0x80//event has been initialized * *};
libevent Management of the event
Starting with the 3 linked list node pointers and a heap index in the event structure, you can generally see how libevent manages the event , which can be found in the following:
Each time an event is turned into a ready state,libevent moves it into active event List[priority] , where the priority is the priority of the event , and then libevent chooses the ready event according to its own scheduling policy, calling its cb_callback () The function performs event processing and populates the parameters of the cb_callback function with the ready handle and event type .
interface functions set for event events
To add an event to libevent , the event object needs to be set first , which is provided by calling the libevent function: Event_set (), Event_base_set (), Event_priority_set ( ) to complete;
void Event_set (struct event *ev, int fd, short events,void (*callback) (int, short, void *), void *arg)
- 1. set event ev binding file descriptor or signal, for timed events, set to -1 OK,
- 2. ev_read| ev_persist, ev_write, ev_signal
- 3. Set the callback function of the event and the parameter arg
- 4. Initializes other fields, such as the default event_base
int Event_base_set (struct event_base *base, struct event *ev)
- Set Event EV will be registered to the Event_base ;
- libevent event_base pointer current_base ev current_base event_base
- If there is more than one in a process libevent instance, you must call the function to Event set a different Event_base ;
int Event_priority_set (struct event *ev, int pri)
- Set Event EV priorities, nothing to say, and one thing to note: when EV when you are in the ready state, you cannot set it back -1 .
Event Processing Framework -event_base
Event_base defines the struct event_base {const struct eventop *evsel in the event-internal.h file; Represents the selected event engine, which may be: Epoll, poll, selectvoid *evbase; The settings for global objects/* Evsel and evbase can be confusing, where you can think of Evsel and evbase as relationships between classes and static functions, such as the invocation behavior when adding events: Evsel->add (evbase, Ev), The actual operation is Evbase, which is equivalent to Class::add (instance, Ev), and instance is an object instance of class. Evsel points to one of the global variables static const struct EVENTOP *eventops[], as mentioned earlier, libevent uniformly encapsulates the I/O Demultiplex mechanism provided by the system into a eventop structure So eventops[] contains several global instance objects, such as Select, poll, Kequeue, and Epoll. Evbase is actually a eventop instance object; First look at the Eventop struct, whose members are a series of function pointers in the event-internal.h file: struct eventop {const char *name;void * (* init) (struct event_base *); Initialize int (*add) (void *, struct event *); Register event Int (*del) (void *, struct event *); Delete Event int (*dispatch) (struct event_base *, void *, struct timeval *); Event distribution void (*dealloc) (struct event_base *, void *); Unregister, release resource int need_reinit;//set if we need to reinitialize the event base}; in other words, in libevent, the implementation of each I/O Demultiplex mechanism must provide this Five function interfaces to perform initialization, destruction, and release of the event, write-offs and distribution. For example, for epoll,libevent implementation of 5 corresponding interface functions, and at the time of initialization and eventop 5 function pointers to the 5 functions, then the program can use Epoll as I/o demultiplex mechanism */int event_count ; /* counts number of total events */int event_count_active; /* counts number of active events */int event_gotterm; /* Set to terminate loop */int Event_break; /* Set to terminate loop immediately *//* active Event Management */struct event_list **activequeues;int nactivequeues;/* Yes A level two pointer, preceded by the Libevent support event priority, so you can think of it as an array, where the element activequeues[priority] is a linked list, and each node of the list points to a ready event with priority prioritized. */struct Evsignal_info Sig; /* Signal handling info, which is to manage the signal of the structure */struct event_list eventqueue;//linked list, holds all the registered event pointers. struct MIN_HEAP timeheap; The stack used to detect if an event timed out is a small Gan struct timeval event_tv that manages timed events; The system's current time struct timeval tv_cache; Compare with Event::ev_timeout to determine if the event timed out//EVENT_TV and Tv_cache are libevent variables for time management};
Create and initialize event_base
Creating a Event_base object also creates a new libevent instance that the program needs to call Event_init ()(internally called Event_base_ The new () function performs a specific operation) to create a function that also initializes the newly generated libevent instance.
The function first applies the space for the event_base instance, then initializes the timer mini-heap, selects and initializes the appropriate demultiplexer mechanism for the system I/O ; Initializes the list of events, and the function also detects the system's time settings, laying the groundwork for later time management.
event_base interface Functions
As mentioned earlier, the role of the Reactor framework is to provide registration and logoff interfaces for events , and to execute event loops based on the system-provided event multiplexing mechanism, when events enter the ready state , the callback function that registers the event is invoked to handle the event . The corresponding interface function in Libevent is mainly:
- int Event_add (struct event *ev, const struct timeval *timeout);
- int Event_del (struct event *ev);
- int Event_base_loop (struct event_base *base, int loops);
- void Event_active (struct event *event, int res, short events);
- void event_process_active (struct event_base *base);
Thelibevent event Loop framework is described in the next article, as described in the code flow that describes the event registration and deletion.
For timed events, these functions invoke the timer heap management interface to perform the insert and delete operations , and for the I/O and Signal Events Call Eventop's Add and the Delete interface functions perform insert and delete operations ( Eventop 's going to Signal Event Invocation Signal processing interface to perform operations);
[Libevent]event,event_base Structure description