--- libev/ev.3 2019/06/20 22:44:59 1.110 +++ libev/ev.3 2019/06/23 02:02:24 1.111 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "LIBEV 3" -.TH LIBEV 3 "2019-06-20" "libev-4.25" "libev - high performance full featured event loop" +.TH LIBEV 3 "2019-06-22" "libev-4.25" "libev - high performance full featured event loop" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -242,10 +242,10 @@ watcher. .SS "\s-1FEATURES\s0" .IX Subsection "FEATURES" -Libev supports \f(CW\*(C`select\*(C'\fR, \f(CW\*(C`poll\*(C'\fR, the Linux-specific \f(CW\*(C`epoll\*(C'\fR, the -BSD-specific \f(CW\*(C`kqueue\*(C'\fR and the Solaris-specific event port mechanisms -for file descriptor events (\f(CW\*(C`ev_io\*(C'\fR), the Linux \f(CW\*(C`inotify\*(C'\fR interface -(for \f(CW\*(C`ev_stat\*(C'\fR), Linux eventfd/signalfd (for faster and cleaner +Libev supports \f(CW\*(C`select\*(C'\fR, \f(CW\*(C`poll\*(C'\fR, the Linux-specific aio and \f(CW\*(C`epoll\*(C'\fR +interfaces, the BSD-specific \f(CW\*(C`kqueue\*(C'\fR and the Solaris-specific event port +mechanisms for file descriptor events (\f(CW\*(C`ev_io\*(C'\fR), the Linux \f(CW\*(C`inotify\*(C'\fR +interface (for \f(CW\*(C`ev_stat\*(C'\fR), Linux eventfd/signalfd (for faster and cleaner inter-thread wakeup (\f(CW\*(C`ev_async\*(C'\fR)/signal handling (\f(CW\*(C`ev_signal\*(C'\fR)) relative timers (\f(CW\*(C`ev_timer\*(C'\fR), absolute timers with customised rescheduling (\f(CW\*(C`ev_periodic\*(C'\fR), synchronous signals (\f(CW\*(C`ev_signal\*(C'\fR), process status @@ -696,7 +696,40 @@ the usage. So sad. .Sp While nominally embeddable in other event loops, this feature is broken in -all kernel versions tested so far. +a lot of kernel revisions, but probably(!) works in current versions. +.Sp +This backend maps \f(CW\*(C`EV_READ\*(C'\fR and \f(CW\*(C`EV_WRITE\*(C'\fR in the same way as +\&\f(CW\*(C`EVBACKEND_POLL\*(C'\fR. +.ie n .IP """EVBACKEND_LINUXAIO"" (value 64, Linux)" 4 +.el .IP "\f(CWEVBACKEND_LINUXAIO\fR (value 64, Linux)" 4 +.IX Item "EVBACKEND_LINUXAIO (value 64, Linux)" +Use the linux-specific linux aio (\fInot\fR \f(CWaio(7)\fR) event interface +available in post\-4.18 kernels. +.Sp +If this backend works for you (as of this writing, it was very +experimental and only supports a subset of file types), it is the best +event interface available on linux and might be well worth it enabling it +\&\- if it isn't available in your kernel this will be detected and another +backend will be chosen. +.Sp +This backend can batch oneshot requests and uses a user-space ring buffer +to receive events. It also doesn't suffer from most of the design problems +of epoll (such as not being able to remove event sources from the epoll +set), and generally sounds too good to be true. Because, this being the +linux kernel, of course it suffers from a whole new set of limitations. +.Sp +For one, it is not easily embeddable (but probably could be done using +an event fd at some extra overhead). It also is subject to various +arbitrary limits that can be configured in \fI/proc/sys/fs/aio\-max\-nr\fR +and \fI/proc/sys/fs/aio\-nr\fR), which could lead to it being skipped during +initialisation. +.Sp +Most problematic in practise, however, is that, like kqueue, it requires +special support from drivers, and, not surprisingly, not all drivers +implement it. For example, in linux 4.19, tcp sockets, pipes, event fds, +files, \fI/dev/null\fR and a few others are supported, but ttys are not, so +this is not (yet?) a generic event polling interface but is probably still +be very useful in a web server or similar program. .Sp This backend maps \f(CW\*(C`EV_READ\*(C'\fR and \f(CW\*(C`EV_WRITE\*(C'\fR in the same way as \&\f(CW\*(C`EVBACKEND_POLL\*(C'\fR. @@ -810,6 +843,14 @@ .Vb 1 \& struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE); .Ve +.Sp +Example: Similarly, on linux, you mgiht want to take advantage of the +linux aio backend if possible, but fall back to something else if that +isn't available. +.Sp +.Vb 1 +\& struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_LINUXAIO); +.Ve .RE .IP "ev_loop_destroy (loop)" 4 .IX Item "ev_loop_destroy (loop)" @@ -1750,13 +1791,13 @@ \fIThe special problem of disappearing file descriptors\fR .IX Subsection "The special problem of disappearing file descriptors" .PP -Some backends (e.g. kqueue, epoll) need to be told about closing a file -descriptor (either due to calling \f(CW\*(C`close\*(C'\fR explicitly or any other means, -such as \f(CW\*(C`dup2\*(C'\fR). The reason is that you register interest in some file -descriptor, but when it goes away, the operating system will silently drop -this interest. If another file descriptor with the same number then is -registered with libev, there is no efficient way to see that this is, in -fact, a different file descriptor. +Some backends (e.g. kqueue, epoll, linuxaio) need to be told about closing +a file descriptor (either due to calling \f(CW\*(C`close\*(C'\fR explicitly or any other +means, such as \f(CW\*(C`dup2\*(C'\fR). The reason is that you register interest in some +file descriptor, but when it goes away, the operating system will silently +drop this interest. If another file descriptor with the same number then +is registered with libev, there is no efficient way to see that this is, +in fact, a different file descriptor. .PP To avoid having to explicitly tell libev about such cases, libev follows the following policy: Each time \f(CW\*(C`ev_io_set\*(C'\fR is being called, libev @@ -1818,9 +1859,10 @@ \fIThe special problem of fork\fR .IX Subsection "The special problem of fork" .PP -Some backends (epoll, kqueue) do not support \f(CW\*(C`fork ()\*(C'\fR at all or exhibit -useless behaviour. Libev fully supports fork, but needs to be told about -it in the child if you want to continue to use it in the child. +Some backends (epoll, kqueue, probably linuxaio) do not support \f(CW\*(C`fork ()\*(C'\fR +at all or exhibit useless behaviour. Libev fully supports fork, but needs +to be told about it in the child if you want to continue to use it in the +child. .PP To support fork in your child processes, you have to call \f(CW\*(C`ev_loop_fork ()\*(C'\fR after a fork in the child, enable \f(CW\*(C`EVFLAG_FORKCHECK\*(C'\fR, or resort to @@ -4569,6 +4611,7 @@ \& ev_select.c only when select backend is enabled \& ev_poll.c only when poll backend is enabled \& ev_epoll.c only when the epoll backend is enabled +\& ev_linuxaio.c only when the linux aio backend is enabled \& ev_kqueue.c only when the kqueue backend is enabled \& ev_port.c only when the solaris port backend is enabled .Ve @@ -4759,6 +4802,12 @@ otherwise another method will be used as fallback. This is the preferred backend for GNU/Linux systems. If undefined, it will be enabled if the headers indicate GNU/Linux + Glibc 2.4 or newer, otherwise disabled. +.IP "\s-1EV_USE_LINUXAIO\s0" 4 +.IX Item "EV_USE_LINUXAIO" +If defined to be \f(CW1\fR, libev will compile in support for the Linux +aio backend. Due to it's currenbt limitations it has to be requested +explicitly. If undefined, it will be enabled on linux, otherwise +disabled. .IP "\s-1EV_USE_KQUEUE\s0" 4 .IX Item "EV_USE_KQUEUE" If defined to be \f(CW1\fR, libev will compile in support for the \s-1BSD\s0 style