Skip to content
Sanne Albreghs edited this page Aug 26, 2022 · 3 revisions

kqueue, kevent, EV_SET - kernel event notificatino mechanism

SYNOPSIS

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

int kqueue(void);

int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout);

EV_SET(&kev, ident, filter, flags, fflags, data, udata);

kqueue()

Creates a new kernel event queue and returns a desciptor.

Provides a method of notifying the user when an event happens or a condition holds, based on the results of small pieces of kernal code termed 'filters'. A kevent is identified by the (ident, filter)pair. There may only be one unique kevent per queue.

The filter is executed upon the initial registratoin of a kevent in order to detect whether a preexisting condition is present. The filter is also executed when an event is passed to the filter for evaluation. If the filter decides that the condition should be reported: the kevent is placed on the kqueue for the user to retrieve.

The filter is also run when the user attempts to retrieve the kevent from the kqueue. If the filter indicates that the condition that triggered the event no longer holds, the kevent is removed from the kqueue and is not returned.

Multiple events that trigger the filter do not result in multiple kevents being placed on the kqueue. The filter will aggregate the events into a single struct kevent.

Calling close() on a fildes will remove any kevents that reference the fildes.

kevent()

Is used to register events with the queue, and return any pending events to the user.
changelist is a pointer to an array of kevent structures (defined in sys/event.h). All changs contained in the changelist are applied before any pending events are read from the queue.
nchanges - gives the size of changelist.
eventlist - a pointer to an array of kevent structures.
nevents - the size of eventlist. It nevents is zero, kevent() will return immediately.
timeout - if not NULL, it specified a maximum interval to wait for an event.

EV_SET()

A macro provided for ease of initializing a kevent structure.

struct kevent {
    uintptr_t	ident;	// identifier for this event
	short		filter;	// filter for event
	u_short		flags;	// action flags for kqueue
	u_int		fflags;	// filter flag value
	int64_t		data;	// filter data value
	void		*udata;	// opaque user data identifier
};

ident - value used to identify this event, the exact interpretation is determined by the attached filter, ident is often a fildes.
filter - identified the kernel filter used to process this event, the pre-defined system filters are described below.
flags - actions to perform on the event.
fflags - filter-specific tags.
data - filter-specific data value.
udata - opaque user-defined value passed through the kernel unchanged.

The flags field can contain the following values: EV_ADD - adds the event to the kqueue, readding an exsiting event will modify the parameters of the original one. Adding an event automatically enables it, uneless overridden by the EV_DISABLE flag.
EV_ENABLE - permit kevent() to return the event if its triggered.
EV_DISABLE - disable the event so kevent() will not return it.
EV_DISPATCH - disable the event soure immediately after dilivery of an event.
EV_DELETE - removes the event from the kqueue, events attached from this fildes are automatically deleted on the last close of the fildes.
EV_RECEIPT - causes kevent() to return with EV_ERROR set without draining any pending events after updating events in the kqueue. Usefull for bulkchanges to kqueue.
EV_ONESHOT - causes the event to return only the first occurrence of the filter being triggered, after the user retrieves the event from the kqueue its deleted.
EV_CLEAR - After the event is retrieved, its state is reset, this is usefull for filters which report state transitions instead of the current state. Some filters may set this flag internally.
EV_EOF - Filters may set this flag to indicate filter specific EOF condition.
EV_ERROR - see return values..

The predifined system filters are filled in below. Arguments may be passed to and from the filter via the fflags and data fields in the kevent structure:

EVFILT_READ
Takes a fildes as the identifier and returns whenever there is data available to read. Sockets which have been passed to listen() return when there is an incoming connection pending. data will contain the size of the listen backlog.

Other socket fildes return when there is data to be read, subject to the SO_RCVLOWAT value of the socket buffer. On return, data contains the number of bytes in the socket buffer.

If the read direction of the socket has shutdown, then the filter also sets EV_EOF in flags and returns the socket error (if any) in fflags. It is possible for EOF to be returned to be returned while there is still data pending in the socket buffer.

EVFILT_WRITE
Takes a fildes as the identifier and return whenever it is possible to write to this fildes. For sockets data will contain the amount of space remaining in the write buffer. The filter will set EV_EOF when the reader disconnects this m ay be cleared by use of EV_CLEAR. For sockets the low water mark and socket error handling is identical to the EVFILT_READ case.

SO_RCVLOWAT - Sets the minimum number of bytes to process for socket input operations. The default value for SO_RCVLOWAT is 1. If SO_RCVLOWAT is set to a larger value, blocking receive calls normally wait until they have received the smaller of the low water mark value or the requested amount. (They may return less than the low water mark if an error occurs, a signal is caught, or the type of data next in the receive queue is different than that returned, e.g. out of band data). This option takes an int value. Note that not all implementations allow this option to be set.

Return values

kqueue() - creates a new kernel event queue and returns a fildes number. If no error creating this kernal. On error -1 is returned.

kevent() - returns the number of events placed in the evenlist, up to the value given bij nevent. If an error occurs while processing an element of the changelist, the event will be placed in the list with EV_ERROR set in flags and the system error set in data. If not enough space -1 will be return with errno set accordingly. kevent() returns 0 when timelimit is passed.