Libevent source Analysis-timer and signal processing

Source: Internet
Author: User

    • Timer handling
    • Signal Processing
    • TIMERFD and SIGNALFD
      • Timerfd
      • Signalfd

Timer handling

In the libevent source Analysis-event processing process, the use of timers, to see the source code:

NULL);//设置定时器事件

Where Evtimer_set is a macro definition

#define evtimer_set(ev, cb, arg)    event_set((ev), -10, (cb), (arg))//event_set原型event *ev, evutil_socket_t fd, short events,      (*callback)(evutil_socket_t, short, void *), void *arg)

You can see the timer event, fd=-1,event=0. An FD-1 event does not occur. When adding an event to Event_base:

event_add(&ev, &tv);//注册事件

You can see that there is a time-out TV. When epoll_wait, there will be a timeout time, timeout.

int epoll_wait(int epfd,structint maxevents,int timeout)

When the timeout is reached, the event has not yet occurred and Epoll_wait will return.
Not so simple in libevent, because there are multiple events monitored, there are many timeouts, and Event_base has a heap that manages timeout

struct min_heap timeheap;

This heap is small Gan. The heap insertion and deletion complexities are log (N). Timer events in the heap are processed after epoll_wait returns

Static voidTimeout_process (structEvent_base *Base){/ * Caller must hold lock. * /    structTimeval now;struct Event*ev;if(Min_heap_empty (&Base->timeheap)) {//Heap is empty        return; } gettime (Base, &now); while(EV = Min_heap_top (&Base->timeheap)) {if(EVUTIL_TIMERCMP (&ev->ev_timeout, &now, >))//value from heap top, find timeout then process             Break;/* Delete This event from the I/O queues */Event_del_internal (EV); Event_debug (("Timeout_process:call%p", Ev->ev_callback)); Event_active_nolock (EV, Ev_timeout,1);//Add time-out to active queue}}

This is the timer handling principle in libevent.

Signal Processing

In libevent, the signal processing is not as simple as a timer. Because the timer can be implemented by waiting timeout, the signal is sent randomly, how to convert to IO?
Using a socket pair in libevent, take a look at a data structure in the Event_base

struct  evsig_info {struct  event  ev_signal; //detection ev_signal_pair[1] Event  evutil_socket_t ev_signal_pair[2 ];    //here is a 2 socket FD  int  ev_signal_added;    //signal is registered  int  ev_n_signals_added;    //added a total of several signals      #ifdef _event_have_sigaction     struct  sigaction **sh_old;    #else   ev_sighandler_t **sh_old;    #endif   int  sh_old_max;/sh_old size};  

This data structure ev_signal_pair[2] is the key to converting signal into IO events. This is actually a pair of socket FD, both of which are local at both ends. Ev_signal_pair[0] As the write end, ev_signal_pair[1] as the FD event. When the signal occurs, write ev_signal_pair[0], you can detect ev_signal_pair[1] readable events.

evsig_initInitialize the signal and put the ev_signal_pair[1] socket as a listener. This function calls the evutil_socketpair(
AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair)
initialization Ev_signal_pair

intEvutil_ersatz_socketpair (intFamilyintTypeintProtocol, evutil_socket_t fd[2]) {evutil_socket_t listener =-1; evutil_socket_t connector =-1; evutil_socket_t acceptor =-1;structSockaddr_in listen_addr;structSockaddr_in connect_addr; ev_socklen_t size;intSaved_errno =-1;if(Protocol | | (Family! = af_inet)) {Evutil_set_socket_error (ERR (Eafnosupport));return-1; }if(!FD) {Evutil_set_socket_error (ERR (EINVAL));return-1; } listener = socket (af_inet, type,0);//Set listen for monitoring    if(Listener <0)return-1;memset(&AMP;LISTEN_ADDR,0,sizeof(LISTEN_ADDR));    listen_addr.sin_family = af_inet; LISTEN_ADDR.SIN_ADDR.S_ADDR = htonl (Inaddr_loopback);//address is nativeListen_addr.sin_port =0;/ * Kernel chooses port. */    if(Bind (Listener, (structSOCKADDR *) &listen_addr,sizeof(LISTEN_ADDR)) == -1)GotoTidy_up_and_fail;if(Listen (Listener,1) == -1)GotoTidy_up_and_fail; Connector = socket (af_inet, type,0);//Initialize active connection End    if(Connector <0)GotoTidy_up_and_fail;/ * We want to find out the port number to connect to. */Size =sizeof(CONNECT_ADDR);if(GetSockName (Listener, (structSOCKADDR *) &connect_addr, &size) = =-1)//Active connection address is native        GotoTidy_up_and_fail;if(Size! =sizeof(CONNECT_ADDR))GotoAbort_tidy_up_and_fail;if(Connect (connector,structSOCKADDR *) &connect_addr,//Initiate connection                sizeof(CONNECT_ADDR)) == -1)GotoTidy_up_and_fail; Size =sizeof(LISTEN_ADDR); Acceptor = Accept (Listener, (structSOCKADDR *) &listen_addr, &size);//Receive connection    if(Acceptor <0)GotoTidy_up_and_fail;if(Size! =sizeof(LISTEN_ADDR))GotoAbort_tidy_up_and_fail;/ * Now check we is talking to ourself by matching port and host on the sockets. */    if(GetSockName (Connector, (structSOCKADDR *) &connect_addr, &size) = =-1)GotoTidy_up_and_fail;if(Size! =sizeof(CONNECT_ADDR) | | Listen_addr.sin_family! = connect_addr.sin_family | | Listen_addr.sin_addr.s_addr! = Connect_addr.sin_addr.s_addr | | Listen_addr.sin_port! = connect_addr.sin_port)GotoAbort_tidy_up_and_fail;    Evutil_closesocket (listener); fd[0] = connector;//write-sidefd[1] = acceptor;//wait for each other to write FD    return 0;}

This pair of socket pairs transforms the signal event into an IO event.

TIMERFD and SIGNALFDTIMERFD

A new TIMERFD is added to the Linux 2.6 kernel to make timers, which are associated with IO
This section describes the implementation of timers in Muduo. Let's look at a new system call for the 2.6 kernel, which can implement a file descriptor based timer based on these system calls. Can be timed so that the file descriptor is readable at a specific time.

#include <sys/timerfd.h>int timerfd_create(intint flags);int timerfd_settime(intint flags,     struct itimerspec *new_value,     struct itimerspec *old_value);int timerfd_gettime(intstruct itimerspec *curr_value);

1, Timerfd_create used to create a timer file, the function return value is a file handle FD.
2. Timerfd_settime is used to set a new time-out period and start timing. A flag of 0 indicates a relative time, and 1 represents an absolute time. New_value the new time for this setting, Old_value is the last time set. Returning 0 indicates that the setting was successful.
3. Timerfd_gettime is used to obtain the time remaining for the timer distance from the next time. If the timer has expired at the time of the call and the timer is in loop mode (the struct itimerspec::it_interval is not 0 when the timeout is set), then the timer starts again after calling this function.

Signalfd

Signal is the method of bringing the signal into the IO event system.

#include <sys/signalfd.h>int signalfd(intconstint flags);

Parameter FD: If 1 indicates a new FD; otherwise it should be an existing file descriptor.
Parameter mask: The set of signals detected by this FD.
Parameter flags: Change the behavior of signal ().

Reference
How to use new Linux API-SIGNALFD

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Libevent source Analysis-timer and signal processing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.