Recipe

kqueue Primer

kqueue is the BSD event notification interface that powers high-performance servers on macOS, FreeBSD, and OpenBSD. Unlike Linux's epoll, kqueue is a unified API for sockets, files, signals, timers, and process events. This primer walks through the core mental model and shows the minimum code to wire it into a Meridian agent loop.

1. The kevent struct

Every kqueue interaction flows through the struct kevent. You fill in an identifier (a file descriptor, signal number, or PID), a filter (what kind of event), and flags (add, delete, oneshot). The kernel returns events using the same struct, so reads and writes share one shape.

2. Registering interest

Call kqueue() once to get a descriptor, then use kevent() to register interest and wait for activity. The same syscall both submits changes and pulls ready events, which keeps the hot loop minimal.

int kq = kqueue();
struct kevent change;
EV_SET(&change, sockfd, EVFILT_READ, EV_ADD, 0, 0, NULL);

struct kevent ev[16];
int n = kevent(kq, &change, 1, ev, 16, NULL);
for (int i = 0; i < n; i++) {
    handle(ev[i].ident, ev[i].filter);
}

3. Beyond sockets

The killer feature is uniformity. EVFILT_VNODE fires on file changes, EVFILT_PROC on process exit, EVFILT_TIMER on intervals, and EVFILT_SIGNAL on signals — all delivered through the same loop. Meridian uses this to consolidate agent supervision, cron firing, and IPC into one descriptor.