Inside Debian Hurd

Dr. Dobb's Journal December 2000

The Hurd's modular design enables customization

By Jerry Epplin

Jerry writes embedded software, primarily for medical devices. He can be contacted at jerryepplin@computer.org.

Over the last couple of years, Linux has gone from being an obscure operating system to one of the most talked-about developments in the computing world. You now see Linus Torvalds on TV, Red Hat Linux in your local software store, and articles in the mainstream press about the challenge Linux poses to Microsoft. Meanwhile, software developers have long been interested in Linux for a variety of reasons, but mainly because of its openness. The operating system itself and many of the applications it runs are open for anyone to view, study, and modify. Its openness is a bonanza for anyone who needs or wants to study the inner workings of a real mainstream OS. When I studied operating systems years ago, it was an almost purely theoretical pursuit, with hands-on activity limited to small projects implementing toy versions of specific operating-system features. Because of the availability of Linux (and other free operating systems such as FreeBSD), today's computer science classes can involve hacking on, and adding features to, a popular mainstream OS. If these projects are done well and address some unmet need, they may end up as features included in Linux and be distributed to millions of users. This serves as a powerful incentive to those learning the OS internals.

For all its virtues as an open operating system, however, Linux -- or specifically the Linux kernel -- throws significant obstacles in the way of developers wishing to modify it. The first thing you encounter when studying it is its sheer size, consisting of thousands of source files. The amount of functionality included in the Linux kernel is impressive but daunting, with everything from the lowest level scheduling and memory management to higher level networking included in the kernel. Also, Linux kernel development is dominated by a hacker ethos, in which external documentation is held in contempt, and even code comments are viewed with suspicion. In such an environment, quick code modification is the top priority, and understandability by the uninitiated is of less importance. The kernel maintainers struggle mightily to keep the source organized rationally, but Linux kernel hacking remains daunting to all but the most dedicated long-term participants.

For this reason among others, the Linux kernel can be considered a rather old-fashioned design. It is what is known as a "monolithic" kernel; that is, one in which all or most operating-system functionality is placed in the kernel proper. When new OS functionality is required -- for example, support for some new networking protocol -- no framework exists in a monolithic-kernel-based OS for placing this functionality elsewhere, so it is simply added to the kernel. The reason for the use of this model for Linux is historical. Linus Torvalds' original goal was ambitious for the hardware available at the time -- he wanted to implement a full UNIX-like operating system on the 386-era hardware then available. Such a goal could only be achieved by squeezing the most useful work out of every available clock cycle. A monolithic kernel allows for very efficient communication between OS components (the components are all compiled together into one large unit), and it can be maintainable if the kernel functionality remains modest. But as kernel functionality is added, maintainability suffers.

Microkernel Architectures

One possible approach to managing OS complexity is the use of an OS based on a "microkernel" architecture, of which the Hurd is a promising example. Originally a project of the Free Software Foundation, the Hurd has caught the interest of a number of other groups. (The Hurd is always referred to as "the Hurd," not just "Hurd." The word stands for "Hird of UNIX-replacing daemons." For more information about the genesis of the Hurd, see http://www.cs.pdx .edu/~trent/gnu/hurd/. "Hird," on the other hand, stands for "Hurd of interfaces representing depth.") Work began on the Hurd in 1990, just before Linux was started, with the goal of it becoming the centerpiece of the GNU operating system. Up to that time, the GNU project and others had already duplicated, using an open-source development model, much of the functionality of UNIX, and especially compilers and other development tools. The goal was to produce a complete open-source UNIX-like OS, and because the kernel of the OS had not yet been developed, the Hurd project was launched to meet that need. Unlike Linux, the Hurd was not focused on a PC architecture; it was intended to be portable and used on the various minicomputers and workstations available at the time. So the GNU project could use a more elegant, if less immediately efficient, design for their kernel.

A microkernel is one in which only the minimum necessary functionality is implemented in the kernel. This would include process creation and deletion, scheduling, memory management, and interrupt handling. Anything else, such as network protocol stacks and interprocess communication primitives, should be handled outside of the kernel in user space. Communication between the kernel and these extra kernel OS facilities is done by clean interfaces, unlike in a monolithic kernel, where components can see and manipulate each other in any ad hoc way they choose. Table 1 lists the advantages of a microkernel.

The maintainability and modifiability advantages of a microkernel-based OS architecture are familiar to anyone who has followed software-engineering practice in the last 20 years, whether on an OS or an application level. This is, after all, what object-oriented programming is all about. One provides only clean, well-defined interfaces to one's objects. Thus a change in the internal representation of, or processing in, the object does not break code that uses the object. On the other hand, access to the internal attributes of a class might provide faster execution for the code that uses the object -- that performance advantage is usually not considered sufficient to justify the resulting added complexity.

The Hurd's attempt at modularity goes beyond using a microkernel with clean interfaces. It also organizes the extra kernel OS facilities into modules called "servers" (or daemons; these are the "UNIX-replacing daemons" referred to in the Hurd acronym). Each provides a fixed set of services to user applications. They communicate with each other, the kernel, and user processes by a set of clean interfaces.

You might reasonably ask why you should be interested in the Hurd, one of many minor operating systems in existence today. Anyone who follows or studies operating-system theory can name dozens of microkernel-based OS projects. Microkernel theory became prevalent in academia about 15 years ago, resulting in a myriad of toy operating systems, the remains of which can easily be found on the Web today. With their projects completed, the creators moved on to new things; microkernels are no longer considered interesting in academia. Many of these operating systems have much to commend them, but few or none will ever see widespread use. It might be tempting to put the Hurd in the same class as these, but several factors separate the Hurd from the mass of minor operating systems.

First, some important players are pushing it forward as an open-source alternative to Linux. Again, the Free Software Foundation is sponsoring the project. Because of its pioneering of the open-source philosophy and its early and continuing development work, the FSF has the respect of many. But perhaps more important is the involvement of the Debian group (http://www.debian.org/), which produces a highly respected and widely used distribution of Linux. The Debian distribution, (called "Debian GNU/Linux" because so much of what most people think of as Linux was produced by the GNU project) is highly regarded by Linux contributers. It might also be considered the purest open-source Linux, because it is not controlled by a commercial operation selling the distribution for profit -- all Debian contributors are volunteers. In any case, the Debian group plans to release a Debian GNU/Hurd distribution that will consist of all of the packages of their Linux distribution, except using the Hurd as the underlying OS. This development is significant because it will ease the transition from Linux to the Hurd for users. Installation and use will be as similar as possible between the Linux and the Hurd distributions. Also, the involvement of the Debian group goes a long way toward ensuring that the Hurd will actually be completed and distributed; the group has a track record of producing a usable OS.

The second factor separating the Hurd from the herd of minor operating systems is that its developers have a commitment to full UNIX compatibility, as well as a plan to meet that commitment. With the involvement of Debian, this primarily means that the Hurd will be Linux compatible. Recall that the original goal of the Hurd development by the FSF was to complete a free UNIX-compatible operating system, all but the kernel of which had already been developed. The project could not possibly be considered complete until all of the GNU utilities and development tools could run under the new operating system. Thus, the Hurd group is highly motivated to develop an OS that can execute UNIX applications. Similarly, the Debian group wants to leverage the Linux packages it has developed. Its only prospect for success is to distribute the Hurd with its already-developed applications. So it is clear that the project participants are motivated to complete a full, usable OS; they are not just experimenting with a toy operating system for research purposes. An examination of the Hurd architecture will reveal why this OS has an appeal that, for some developers, exceeds that of Linux.

Overall Hurd Architecture

As previously mentioned, the Hurd consists of a microkernel at its core, and a set of servers surrounding it, providing services to applications. A design goal is for the microkernel to be interchangeable, so a designer could remove the default kernel and replace it with another; for example, one with a different scheduling or memory-management algorithm. For now, however, the Hurd is fairly tightly bound to the Mach microkernel, one of the original and more well-known microkernels. Mach has a number of versions and variants -- the one currently used by the Hurd is GNU Mach, an open-source Mach developed as part of the GNU project. Surrounding Mach are the servers (that is, independent daemons with well-defined interfaces among them) and the applications.

The Mach Microkernel

Mach is a fairly well-known microkernel. If you've taken an operating-systems course in the past 10 years, you probably studied it. Mach is billed as an object-oriented kernel -- purists will call this a stretch, as it's written in C, and has no inheritance or polymorphism. Nevertheless, Mach can be seen as consisting of the following classes: ports, messages, tasks, threads, and virtual memory. As with well-designed OO systems, the interfaces to these classes are well defined and stable, so internal changes to the classes do not break the code that uses them.

A Mach task corresponds roughly to a process in a UNIX environment. It is an execution environment representing the resources in use by a running program, such as virtual memory or processor cycles. But in contrast to a traditional UNIX process, a Mach task does not implicitly contain one thread of execution -- a Mach thread is a separate object. Thus, a useful task must contain at least one thread. Threads in the Mach context are the same as in most modern operating systems such as UNIX or Windows -- an execution thread sharing memory and other resources with other potential threads in its containing task. Mach was designed from the ground up to be aggressively multithreaded and to run efficiently on multiprocessors. In contrast, Linux started as a rather traditional single-thread-process-oriented OS, with multithreading and multiprocessing added only recently. Full multithreading has only been possible in Linux since the fairly recent widespread use of the glibc C library, while multiprocessing is an ongoing effort that is not yet complete. In any case, Mach and the Hurd were designed to support these concepts from the very beginning.

The primary means of communication among Mach tasks is the port. A Mach port is somewhat analogous to a port in the context of socket-based communication -- a channel of communication between two tasks. Like ports in a socket environment, Mach ports are designed to behave identically whether the communicating threads are executing on the same processor, on separate processors in a multiprocessing environment, or on different computers on a network. And because ports are the preferred means of intertask communication in a Mach application, this design makes it easy to scale applications up using multiprocessing. Also, the data content to be communicated is in the form of messages, which are themselves formal Mach objects. Finally, Mach provides memory-management services, as well as functions for sharing memory among tasks.

The Hurd Servers

The Mach microkernel has a number of other features, but from the Hurd point of view, these are not important. The Hurd simply needs a microkernel that provides the essential functions of a kernel: scheduling, task creation and destruction, IPC, and memory management. In fact, in principle, another microkernel having these facilities could be substituted for Mach, thereby facilitating Hurd portability; but currently Mach is the only kernel used with the Hurd. Aside from its microkernel basis, perhaps the most interesting technical aspect of the Hurd is its multiserver design. The multiple servers surrounding the microkernel run in user mode, providing services to application programs. A look at some of the Hurd's servers and other features may clarify this design.

The authentication server provides user identification for tasks wishing to communicate with one another. A task can verify the identity of another by connecting to a port on the authentication server and using its services. Thus the authentication server provides essential security mechanisms for the Hurd. But note that it has no special status itself -- it is a user-space program like all other Hurd servers. Thus anyone can design and run his or her own authentication server; other users are free to use it if they trust it, or ignore it if they don't.

The process server essentially acts as a bridge between the UNIX concept of a process and the Mach-task concept. POSIX-standard UNIX has some process concepts that are not supported by Mach -- this missing functionality is provided in the process server. It also provides system-wide process information -- tasks can register with the process server, so other tasks (for example, a UNIX-style process server program) can obtain information on all system tasks. The use of the process server is optional; a process need not register itself with the process server, in which case others cannot obtain information on it.

The Hurd consists of a number of other servers, including those for socket-based communication, NFS, and many others. Servers have come and gone as the Hurd development has progressed. Keep in mind that a user is free to add servers at will -- no special permissions are needed.

Besides servers, another key Hurd concept is that of translators. Up to a point, you can think of translators as an elegant way of implementing such familiar UNIX-type filesystem features as mount points, devices, and symbolic links. Each file in the Hurd file hierarchy is associated with a program called a "translator." When a user program accesses this file, control is passed to the translator to handle the operation. If the access is a read of an actual disk file, the translator for the file system type acquires the data from the disk and returns it to the application. If the access is to a device, the device driver for that device type handles the call. Similarly for a symbolic link -- a translator can simply redirect an access to somewhere else in the file hierarchy.

So far, translators provide nothing that cannot be found in standard UNIX systems, which already provide unified access to files, devices, and links. But Hurd translators can be applied to any kind of data. One example is FTP access. Files on remote systems can be mapped into your file hierarchy (at, for example, /ftp/ftp.mydomain.com/pub/myfile) and copied, deleted, or edited with the same tools you use on local files. The translator simply translates the normal file access function calls into those FTP operations needed to fill the request. You can easily imagine other useful translators. Hierarchically arranged data in a database could be exposed for browsing by means of cat, ls, and so on. Or a network administration tool could be implemented, with all computers on the local network mapped into a local directory. Cat would list network data such as the machine's IP address. Those machines that are gateways could simultaneously be viewed as directories -- by executing a cd to a gateway, the computers on the connected subnet might be visible. As with servers, translators require no special privileges. Anyone can write one, debug it, and experiment with it until it is ready for use by other users.

Current Hurd Status

For all its promise, it is too early to recommend the Hurd for the average user. As of this writing, the operating system is missing some basic functionality, and it is not expected to be usable from a user's perspective for some time. The Hurd currently does little or nothing that cannot be done with Linux. Still, an experienced Linux hacker will find the Hurd manageable, and if you are interested in contributing to the effort, some parts of the porting and implementation effort are available. Because of its elegance, most programmers will find the Hurd somewhat easier to understand than Linux.

Besides understandability, the Hurd's modular design allows for endless customization. We've seen how servers can be added or removed with relative ease; and how the microkernel will, with time, be replaceable as well. It is easy to imagine seeing the Hurd variants for a variety of special purposes, especially embedded applications. Perhaps GNU Mach would be replaced by some real-time microkernel (a real-time Mach is available), and a number of unneeded servers would be eliminated. With minimal effort, we could implement a full real-time operating system customized to the application at hand. An embedded application needing a small footprint could eliminate all but a few needed servers, while higher end apps could run with more. All applications could be developed on the same desktop OS. One of the appeals of Linux is that it offers the freedom to produce a custom OS for your purposes. The Hurd has the potential to turn that freedom into a practical possibility.

DDJ