Ideas I miss: Microkernels



You’re probably reading this post on a Monolithic OS of some kind: A computer running windows, mac, linux, or a BSD. There are some microkernel features in them, but since most of them run a single process in kernel space, I’m going to call them monolithic OSes and you can’t stop me.

Microkernels, like Minix (the inspiration for Linux) and Mach (the inspiration for Mac OS X), relegate as little as possible to kernel space, and instead work by passing messages from user space to various services that can exist in kernel or user space. This allows for a very minimal implementation of a kernel – Minix’s first release was only 12,000 lines of C code. In fact, the entirety of the OS can be implemented with just two system calls, send and receive. Linux currently has hundreds of system calls, some of which are deprecated but can’t be removed, multiple ways to duplicate a file descriptor, and multiple ways to fork a new process. Minix can implement the entire POSIX system call interface with just these two calls.

Microkernels are also more secure, since an exploit to one part of the kernel, like the drivers doesn’t affect any other service. In a monolithic kernel, a faulty driver can bring down the entire system, since the kernel runs on one process, or worse, exfiltrate data, as drivers have elevated permissions when running in a monolithic kernel. Kernel extensions are also problematic, since they can run as root and users may download arbitrary extensions from the internet without vetting them. In Minix, the file system, memory management, drivers, can all be run as separate processes, even in user space. Thus, the worst an exploit to any of these services can do is crash or compromise that particular service. If you compromise a service in user space, you basically do nothing, since all code runs in user space.

Microkernels also allow for independent evolution of parts of the OS in a way a monolithic kernel cannot. In a microkernel, writing your own file system, network stack, or device driver is a cinch, since it’s working on a service that reacts to messages. You parse the message, do a relevant action, return a relevant response, and continue on. If you want to make a part of the service more efficient, you can test it easily, benchmark it, and keep iterating. In a monolithic kernel, some parts are hopelessly intertwined with the rest of the system. To write and test out a file system, you have to mock out the rest of the kernel or compile your file system with the rest of the Linux kernel. To test out the scheduler or networking capabilities, you have to do the same.

The resurgence of Microkernels

Linux developers got tired of always having to go into the kernel to make a change. If I want to improve a scheduler, I shouldn’t have to know about anything other than tasks. Fundamentally, a scheduler should see a list of tasks that want to run, some information about each task, pick one, and run it for some time before restarting. That’s it. I should be able to judge whether or not my change was good without thinking about the rest of the system. If I want to debug some code that runs in the kernel, I should have a way to do so that doesn’t involve peeking into the kernel. What was the solution? Creating user space equivalents of critical kernel space facilities, like the following:

Lots of users may want to customize parts of their OS, tweaking subsystems to optimize their use cases. Computing has become more heterogeneous, and users have more diverse needs than ever, since they use a plethora of devices like embedded devices, phones, tablets, laptops, desktops, cloud daily. It’s impossible for a single monolith to make all the right choices for every user. Instead, imagine a distribution of Linux that really cared about power consumption, so it decided to pick power efficient subsystems, or a hyperscaler distribution that optimized for virtualization. It’s hard to do with current linux, but with the changes coming in the future to break up the monolithic kernels into distinct services, maybe the microkernel future will be coming soon.