Please note that this is a Libev rather than a libevent article.
This article is the third, mainly about the basic concentration of watcher in Libev.
This address: https://segmentfault.com/a/1190000006679929 ev_io: direct Operation FD
This watcher is responsible for detecting whether the file descriptor (hereinafter referred to as FD) can write data or read the data. It is best to set FD to be non-blocking.
Note that sometimes there is no data when you call read (return 0), when a non-blocking read gets a eagain error.
(The following two special questions are specifically mentioned in the Libev documentation, but I don't quite understand ...). ) The special problem of the missing FD
Some systems need to explicitly call close (such as Kqueue, Epoll), otherwise when a FD disappears, and the new FD enters, occupying the same FD number, Libev does not know that this is a new FD.
The solution on the Libev side is to assume that this is a new FD every time you call Ev_io_set. special problems with using DUP to manipulate FD
Some backend (backend) cannot register for ordinary FD events and can only register underlying file descriptions, which means that using DUP () or other strangely manipulated FD can only be received by one of them.
This does not have a valid workaround unless you set the backend to Backend_select or Evbackend_poll Special questions about the file
Ev_io for file Tears said no use, as long as the file exists, there will be time. For stdin and stdout, use caution and make sure that the two are not redirected to the file. special questions about fork
Remember to use ev_loop_fork and use Evflag_forkcheck. But there's no need to worry about Epoll and kqueue. questions about the Sigpipe
Just a reminder: Remember to handle the Sigpipe event. about accept an unacceptable connection
Most POSIX Accpet implementations produce an incorrect operation when deleting a connection caused by an error, such as an FD reaching the upper limit, such as making the accept fail but not rejecting the connection, producing only enfile errors. However, this can cause Libev to be marked as ready state.
The recommended method is to list all errors and log them, or to temporarily close the watchers. related Functions
void Ev_io_init (Ev_io *, callback, int fd, int events)
void Ev_io_set (EV) IO *, int fd, int events)
Where events can be a combination of ev_write and ev_read. Example
static void stdin_readable_db (struct ev_loop *loop,
ev_io *w,
int revents)
{
ev_io_stop (loop, W)
...... Read
}
from W->FD ... Some_init_func ()
{
...
struct Ev_loop *loop = ev_default_init (0);
Ev_io stdin_readable;
Ev_io_init (&stdin_readable, stdin_readable_db, Stdin_fileno, ev_read);
Ev_io_start (Loop, &stdin_readable);
Ev_run (loop, 0);
...
}
Ev_timer: relative timeout mechanism
The Libev provides a timer with a relative timeout mechanism. The so-called "relative", that is, the parameter of the timer is: Specify the current time as the benchmark, how long to delay the departure event. This timer is independent of the date/time based on the perpetual calendar and is based only on the system monotonic time. Cycle Timer Design
The following is an example of a 60-second cycle timer that illustrates the different strategies for using Ev_timer 1. Reset using standard initialization and stop APIs
Ev_timer_init (Timer, callback, 60.0, 6.0);
Ev_timer_start (loop, timer)
Standard settings. Or--
Ev_timer_stop (loop, timer);
Ev_timer_set (timer, 60.0, 0.0);
Ev_timer_start (loop, timer)
This setting stops the timer whenever there is an active time, and restarts it. The first parameter is the first time-out, and the second parameter is the fixed time-out for the second start. However, this method is relatively simple, but the time is not stable, and the overhead is 2. Use Ev_timer_again reset
With Ev_timer_again, you can ignore Ev_timer_start
Ev_init (timer, callback);
Timer->repeat = 60.0;
Ev_timer_again (loop, start);
When the above initialization is complete, it is called in callback:
Timer->repeat = 60.0;
Ev_timer_again (loop, timer);
You can change the timeout value, regardless of whether the timer is active 3. Let the timer timeout, but reconfigure as appropriate
The basic idea of this approach is that many timeout times are much larger than interval, so remember the last active time, and then check the real timeout in callback.
Ev_tstamp g_timeout = 60.0;
Ev_tstamp g_last_activity;
Ev_timer G_timer;
static void Callback (Ev_p_ev_timer *w, int revents)
{
Ev_tstamp after = G_last_activity-ev_now (ev_a) + G_timeou t;
If less than 0, indicates that the time has already occurred, has timed out
if (after < 0.0) {
... A timeout operation
was performed}
else {
//callback was called, but there were some recent active actions that did not time out
//At this time the new timeout event to be set as needed to handle
ev_ Timer_set (W, after, 0.0);
Ev_timer_start (Loop, G_timer);
}
}
Enable this mode, remember to set g_last_activity to Ev_now when initializing, and call once callback (loop, &g_timer, 0); When the active time arrives, just modify the global timeout variable and then call it again Callback
G_timeout = New_value
ev_timer_stop (Loop, &timer)
callback (loop, &g_timer, 0)
4. Use a doubly linked list for a timer
Usage scenario: There are thousands of requests, and all require timeouts
Calculates the value of timeout before timeout starts, and places a timeout at the end of the list. Then when the item in front of the list needs fire. Use Ev_timer to fire it off.
When there is activity, the timer is taken from one of the list, re-calculated by timeout, and appended to the end of the list, to ensure that if Ev_timer has been removed by the first item of the list, update it "too early" problem
Assuming that the request is delayed for 1 seconds at 500.9 seconds, then when the 501 second arrives it may cause a timeout, which is the "too early" issue. The Libev strategy is to perform a timeout of 502 seconds for this scenario. But this is a "too late" issue, please note the programmer. the problem of "suspended animation"
suspenged animation, also known as hibernation, refers to putting the machine into hibernation. Note that different systems may not behave the same.
One kind of hibernation is making all the programs feel just a little bit of time in general (time hopping)
It is recommended to call Ev_suspend and Ev_resume Other points of attention in SIGTSTP processing
Ev_now_update () is expensive, please use it carefully
The Libev uses an internal monotone clock instead of the system clock, while the Ev_timer is based on the system clock, so the comparison is done in a different step. related Functions
void Ev_timer_init (Ev_timer *, Callback, ev_tstamp after, Ev_tstamp repeat);
void Ev_timer_set (Ev_timer *, ev_tstamp after, Ev_tstamp repeat);
If the repeat is positive, the timer will be triggered repeatedly, or only once.
void Ev_timer_again (Loop, Ev_timer *)
Ev_tstamp ev_timer_remaining (Loop, Ev_timer *)
ev_periodic: Calendar-Based Timers
related Functions