Those of us who have been extremely online for a very long time will remember that Linus Torvalds announced his Linux kernel to a usenet newsgroup (or “froup”, as the internet lexicon had it at the time) for the Minix operating system. Minix is a Unix-like operating system that Andrew S. Tanenbaum created to teach his class on operating systems, and that he published in the book “Operating Systems: Design & Implementation”.
Minix uses a microkernel design, in which the kernel is responsible for a limited subset of system services—typically, process scheduling and inter-process communication (IPC) are all that is needed—and everything else runs as a process in “user space”, including device drivers, file systems, and virtual memory managers, in addition to the “applications” that you actually bought the computer to use. The typical alternative is the approach that Torvalds chose for Linux: a monolithic kernel, in which operating system services all run in the kernel, and user space processes provide applications.
Each design has its trade-offs. The kernel is a single, high-privilege space where any code running has very little restriction, so the microkernel approach reduces the “blast radius” of the security risk by strongly restricting the amount of code that runs in the kernel. Because all operating system services happen using IPC, a microkernel can further define the security controls in place in a running system by limiting which processes can communicate with which other processes—and it can do so dynamically, so that a process might be able to make some calls but not others, or make a call at one time that it cannot at another time.
However, all of this IPC comes at a cost, as any system call that an application makes might translate into multiple IPC communications, in which the calling process needs to rewrite its data to fit the interface format of the protocol with the receiving process, then tell the kernel to receive the message, which write the data into the receiving process’s memory space and schedules that process to run. Additionally, microkernel designs run the risk of an “upcall deadlock”, where the kernel cannot make progress because it is waiting on a user-space process that is blocked in a system call. As an example, imagine that an application needs to open a file, and the filesystem process encounters an error that it tries to write to the kernel’s log—which is on the filesystem that encounters the error.
Conversely, the monolithic kernel design makes it easier for any kernel component to directly access any other kernel component: faster, harder to deadlock, but easier to create bugs in and easier to exploit. All those drivers running in the privileged kernel memory space, potentially from multiple vendors or other sources, introduce risks of potentially exploitable problems at the core of the operating system.
Tanenbaum and Torvalds famously had some heated discussions about the relative merits of each architecture, which probably seemed important at the time but are less relevant these days as the microkernel design eventually won out in many contexts (consider mobile phone baseband environments and car management systems, which typically run microkernels like QNX or an L4 derivative), with a hybrid approach (Windows NT is a microkernel design that runs a lot of services in the kernel for performance, and XNU—macOS, iOS etc.—is a microkernel with a monolithic kernel grafted on, but that then runs a lot of secure services in out-of-kernel “exclave” environments) also being popular. At this point, the outlier is the one frequently-observed monolithic kernel design in the wild: Linux.
Anyway, back to that announcement. Torvalds explained that Linux was a hobby project, and “won’t be big and professional like GNU”. Well, these days, Linux is at the core of most operating environments that use GNU software, to the point that they are called “Linux distros” no matter how much some people might like everyone to call them “GNU plus Linux”. So what gives?
The GNU project started in 1984—a full seven years before that Usenet announcement—as a small collection of tools under an umbrella project whose creator’s aim was to offer a full replacement for a UNIX operating system that preserves and promotes the “four freedoms” of free software. Initially, those tools were the GNU Emacs text editor and the GNU C Compiler (later GNU Compiler Collection), both created by project leader Richard M Stallman. During the next few years, people contributed other components to the GNU system and built them in a way that meant they work on many different flavors of UNIX and UNIX-like operating systems, as well as less UNIX-like environments including the Amiga and Windows. However, the whole environment could not be free because there was no GNU kernel (the closest alternative being the BSD kernel, which had licensing restrictions that were interpreted as not freedom-respecting, and which was soon to become embroiled in a lawsuit with the original UNIX creators, AT&T).
The effort to create a kernel, known as Trix, was not close to ready. Eventually the GNU project entered into an agreement with Carnegie-Mellon University to use their Mach kernel (actually in May 1991, after Torvalds had begun work on Linux). Mach is found in operating systems you likely have not used including OSF/1 and NEXTSTEP, and operating systems you may well have used if you have been near the Apple galaxy since about 1997—or earlier, if you are one of the few people who used Tenon’s MachTen or Apple’s MkLinux. Reigniting that debate about monoliths or microkernels, GNU Mach—the GNU project’s own implementation of Mach 3, begun in 1997—operates as a microkernel that loads the Hurd (HIRD of UNIX-Replacing Daemons, where HIRD stands for HURD of Interfaces Representing Depth, where HURD…you get the idea). Immediately snuffing the debate back out, GNU plus Linux is used and useful, where GNU (including the Hurd) has been perpetually “nearly ready” for the intervening decades, including several attempts to replatform the whole system on to a different microkernel (the L4 family of microkernels, Coyotos’ microkernel, and a new project called Viengoos have all been candidates).
Well, this is a nice story, but I am afraid it is out of date. At some point last year, GNU Hurd became relevant again, which long-time contributor Samuel Thibault explained to a packed room at the FOSDEM conference earlier this year. A port of the Rust compiler greatly increased the amount of application software available. A 64-bit port of GNU Mach and GNU MIG (the Mach Interface Generator, the interface description language that describes the data structures Mach processes use for IPC) is complete, so the OS can take advantage of modern processors and large amounts of system memory. When I say “modern processors”, x86_64 support is mostly ready, and AArch64 (64-bit ARM) is experimental.
By running a “rump” NetBSD kernel in user-space, Mach gets modern networking, USB, and other drivers so that it can actually run on computers that contain those modern processors. Long-dormant multiprocessor code (CMU Mach was originally designed for supercomputers, which were envisioned at the time as symmetric multiprocessing systems) has been rewritten, so that GNU Mach is now multicore, albeit with most Hurd processes still residing on a single core while the team audits their parallelism safety. Journaling filesystems are nearly ready.
So complete is GNU Mach and GNU Hurd, that the GNU Guix system offers it as an alternative kernel choice in the installer, if you do not want to use the Linux-libre default kernel. There has been a Debian GNU/Hurd distribution for donkey’s years. It may have been April Fool’s when Gentoo announced that they were switching to the Hurd, but the availability of scripts and a virtual machine image with running Gentoo/Hurd was no joke. Your author is running it now, with this repository checked out in git and the GNU emacs editor making some final corrections to this article.
Today, GNU is fully usable, it is just not big and professional like GNU plus Linux. Some of the ideas that had to be bolted on to Linux to make it “big and professional” are native parts of the design when you use GNU Mach and the Hurd. Making isolated environments like the podman containers we use to create and publish “De Programmatica Ipsum” requires an unholy amalgam of cgroups, namespaces, and other features that Linux has sprouted over time. In a Hurd system, you just define and launch a subhurd: an independent set of the UNIX-replacing daemons that has limited access to the host HURD’s capabilities. GNU Guix also offers the intriguing possibility of the “childhurd”—a Hurd environment you define and run in your Linux-based Guix environment.
If your idea of the Hurd is that it was a nice idea once upon a time that never came to anything, I would recommend revisiting it now. You will be pleasantly surprised.
Cover photo by Helena Pfisterer on Unsplash.