5 ms·
Is this correct? How I interpreted the author: - kqueue : Designed to work off of concrete event filters. New event types mean kqueue must be rengineered su
by nobodyandproud 2y ago
Is this correct? How I interpreted the author:
- kqueue : Designed to work off of concrete event filters. New event types mean kqueue must be rengineered support it (at the very least, a new event filter type).
Versus
- epoll : Designed to work off of kernel handles. The actual event type isn’t the concern of epoll and therefore epoll itself remains unaffected if a new event type were introduced.
I’m guessing composibility is mentioned because of this decoupling? I’d think a better explanation would be single-responsibility, but I’m likely not understanding the author correctly here.
- adrian_b 2y agoI have not looked at kqueue, but there is no reason to believe that it would be affected by the introduction of a new event filter more than epoll is affected by the introduction of a new system call that creates a new kind of pseudo-file handles that can be passed to epoll. The event filters must have a standard interface, so adding one more kind should not matter for kqueue more than the existence of a new kind of "file" handle matters for epoll. The epoll API makes opaque for the user the differences between the kinds of kernel handles, but at some point inside the kernel the handles must be disambiguated and appropriate actions for each kind of handle must be performed, exactly like in kqueue various kinds of event filters must be invoked.
- nobodyandproud 2y agoRight. I’ve never worked in the kernel space, but I wanted to understand the author. As you mentioned, event handlers still only care for certain messages and ignore others, so the disambiguation must happen. Rereading it; what’s also not clear to me is whether epoll is a single queue, or one queue for each subsystem and handle type. From a handler’s perspective, it seems like an implementation detail? Again, I don’t know about this stuff; just hoping someone knowledgeable can help clear it up.
- markjdb 2y agoI don't think the article does a good job of arguing its premise, which I think is that kqueue is a less general interface than epoll. When adding a new descriptor type, one can define semantics for existing filters (e.g., EVFILT_READ) as one pleases. To give an example, FreeBSD has EVFILT_PROCDESC to watch for events on process descriptors, which are basically analogous to pidfds. Right now, using that filter kevent() can tell you that the process referenced by a procdesc has exited. That could have been defined using the EVFILT_READ filter instead of or in addition to adding EVFILT_PROCDESC. There was no specific need to introduce EVFILT_PROCDESC, except that the implementor presumably wanted to leave space to add additional event types, and it seemed cleaner to introduce a new EVFILT_PROCDESC filter. Process descriptors don't implement EVFILT_READ today, but there's no reason they can't. So if one wants to define a new event type using kevent(), one has the option of adding a new definition (new filter, new note type for an existing filter, etc.), or adding a new type of file descriptor which implements EVFILT_READ and other "standard" filters. kqueue doesn't really constrain you either way. In FreeBSD, most of the filter types correspond to non-fd-based events. But nothing stops one from adding new fd types for similar purposes. For instance, we have both EVFILT_TIMER (a non-fd event filter) and timerfd (which implements EVFILT_READ and in particular didn't need a new filter). Both are roughly equivalent; the latter behaves more like a regular file descriptor from kqueue's perspective, which might be better, but it'd be nice to see an example illustrating how. One could argue that the simultaneous existence of timerfds and EVFILT_TIMER is technical debt, but that's not really kqueue's fault. EVFILT_TIMER has been around forever, and timerfd was added to improve Linux compatibility. So, I think the article is misguided. In particular, the claim that "any time you want kqueue to do something new, you have to add a new type of event filter" is just wrong. I'm not arguing that there isn't technical debt here, but it's not really because of kqueue's design.
- nobodyandproud 2y agoThanks. Then it seems like there are more similarities than differences here: Both solve the same problem of “select” by being the central (kernel-level) events queue; though with different APIs. The other bit that caught my eye was the author saying epoll can do nearly everything kqueue can do. What is that slight bit that epoll can’t do?
- oasisaimlessly 2y agoAFAIK, just aio[1] (async file IO). [1]: https://man.freebsd.org/cgi/man.cgi?query=aio&sektion=4&apropos=0&manpath=FreeBSD+14.2-RELEASE+and+Ports https://man.freebsd.org/cgi/man.cgi?query=aio&sektion=4&apro...
- markjdb 2y agoI'm not sure. Maybe it's "wait for events that aren't tied to an fd." For instance, FreeBSD (and I think other BSDs) also have EVFILT_PROC, which lets you monitor a PID (not an fd) for events. One such event is NOTE_FORK, i.e., the monitored process just forked. Can you wait for such events with epoll? I'm not sure. More generally, suppose you wanted to automatically start watching all descendants of the process for events as well. If I was required to use a separate fd to monitor that child process, then upon getting the fork event I'd have to somehow obtain an fd for that child process and then tell epoll about it, and in that window I may have missed the child process forking off a grandchild. I'm not sure how to solve this kind of problem in the epoll world. I guess you could introduce a new fd type which represents a process and all of its descendants, and define some semantics for how epoll reports events on that fd type. In FreeBSD we can just have a dedicated EVFILT_PROC filter, no need for a new fd type. I'm not really sure whether that's better or worse.