InformIT

10 Things I Hate About U(NIX) Revisited: Readers Speak

Date: Mar 17, 2006

Return to the article

After receiving several comments (and insults) to his November 2005 article on hating UNIX, David Chisnall offers his responses and further insight on his continuing disdain for UNIX.

My recent article entitled "10 Things I Hate About U(NIX)" provoked a number of comments, questions, and insults. I have tried to address some of them here.

1. You’re really a Microsoft shill, aren’t you?

No. I haven’t used a Microsoft operating system for two years with the exception of a small Windows partition I keep around on my ThinkPad for the occasional game. The only Microsoft product I routinely use is Microsoft VirtualPC, and that’s a version that pre-dates the company’s purchase of Connectix with an update that replaced the original branding with Microsoft logs. It is a constant source of amusement to me that the software gives all Windows executables a Microsoft logo, so whenever I receive an email virus I can tell instantly from the Windows icon it acquires.

The operating systems I use on a daily basis are Mac OS X, FreeBSD, OpenBSD, and Linux. Of these, OpenBSD is probably my favorite; it has first-rate documentation and a clear and consistent layout. Oh, and decent security, too.

2. But Microsoft did pay you, right?

No. I was paid by Informit, who may (directly or indirectly) receive advertising revenue from Microsoft, but because the idea for the article came from me and not them, this did not have any bearing on my decision to write it. Of course, if anyone from Microsoft is reading this and wants to give me some money then they can, as long as I don’t have to do anything.

3. You hate Linux, though?

Hate is a strong word. I have used Linux on and off for some years, and I do find parts of the system frustrating. My main problems of Linux are the lack of consistency between distributions and the fact that I never really liked System V (I’m more of a BSD person).

Having said that, I do keep a Linux machine in my coat pocket, although I would be quite tempted to replace it with NetBSD if it gets ported...

4. And you think we should all use Windows?

I have a great deal of respect for David Cutler’s work on both VMS and Windows NT. Unfortunately, Microsoft decided to take an elegant and flexible kernel architecture and build a quite atrocious pile of hacks on top of it in the name of backwards compatibility.

In 2001, Apple demonstrated the correct way of maintaining backwards compatibility with a poorly-designed legacy operating system—you build an emulated environment into your system and run legacy code there. Even before then, Windows 3.x had made use of the primitive 8086 virtualization features to run legacy DOS applications. The route Microsoft took was to port its legacy APIs and ABIs. Even today, Microsoft is reaping the benefits of this with features such as the WMF vulnerabilities.

I still believe the core design of the Windows NT kernel to be sound, and watch the ReactOS project with interest.

5. I am surprised you didn’t mention UNIX security. What do you think of capability-oriented systems?

Every so often someone sits down and says to himself, "Security isn’t complicated enough. What would be really good would be if no one understood how to do it properly."

One thing the Windows kernel does really well is security. Every single object has an associated access control list, which allows fine-grained access control to pretty much anything. The average user’s response to this is to decide it’s too complicated to understand, and that the simplest thing to do is set everything to full access.

UNIX, in contrast, has a very stupid security model. File permissions are simple, and many other things are very coarse-grained—you are either root, or you can’t do them. Some more complicated things have been built on top, but often these get disabled. In spite of this, UNIX systems remain more secure.

Someone will, no doubt, point out that VMS has a similar security system to Windows, and an even better security record than Windows. I would argue that this is due to three factors:

My current favorite UNIX system is OpenBSD, which has a reputation for security. Part of the reason for this is that they have an aggressive policy of code review. Another, more significant, part is their attitude to security, which can be summed up by their slogan "Secure by Default." If the user is required to do anything to secure the system, then it’s not secure. If the user is required to unsecure the system in order to use it, then it is not secure.

Designing a good capability-oriented security system is typically viewed as an operating systems problem. It is not. Capability-oriented systems have been around for a while. Even UNIX is getting similar features in the form of things like TrustedBSD, Trusted Solaris, and SELinux. The real problem is designing a user interface that is both easy to use and doesn’t encourage the user to just click OK when a random piece of malware asks for all permissions. Until this problem is solved, I am skeptical about capability models, and very few people in the capability community seem willing to admit that the problem exists, let alone address it.

6. You criticize UNIX and say that Mach has some features it lacks, but isn’t Mach a form of UNIX?

I have something of a soft spot for Mach. It is a perfect example of why you should never let theoreticians design real software, but on paper it is a thing of beauty.

The Mach microkernel was highly experimental and made a number of design decisions that turned out, in retrospect, to be very bad. The most notable relates to port rights.

All interprocess communication in Mach (including most interaction with the kernel) happens via ports—things that can have messages written to them. Each process has a set of permissions for various ports determining whether it is allowed to read or write from them. Every time you write to a port, the kernel checks that you are allowed to do so, and then lets you if you are.

This sounds sensible—you don’t want arbitrary people writing into your IPC mechanisms. Unfortunately, it turns out that this permission checking is rather an expensive thing to do. Worse, it turns out that 90 percent of the time it isn’t of much use. A better solution is to add some information about the message sender to the message, and allow the receiver to do the checking if it wants to. Going the Mach route makes system calls in Mach-based systems (including OS X) about 10 times more expensive as in other systems.

The point of this has been to reinforce the idea that Mach is not UNIX. It is possible to build a UNIX-like system on top of Mach in the same way that it is possible to build a DOS or OS/2-like system on top of Windows NT, but Windows NT is not DOS or OS/2.

7. Putting wildcard expansion in the shell isn’t a bug, it’s a feature.

Very early UNIX systems could only run one process at a time. Whenever a context switch occurred, it flushed the changed RAM to out-of-core storage and loaded the new process from swap. The implementation of fork() as a mechanism for creating new processes seemed logical—you already had a copy of the parent process in-core, so you acquired the copy for free.

The system itself ran on a PDP-7. This machine lacked many features that modern computer users take for granted, such as a memory management unit. There were no shared libraries—UNIX didn’t get these until it was 15 years old. Putting wildcard expansion in the shell was not a conscious decision; there was simply nowhere else to put it.

In a modern operating system, this functionality would obviously go in a shared library, but by the time such advances came to UNIX, 15 years of tradition was telling developers that wildcard expansion belonged in the shell. Anyone wanting to write a new shell had written his own (often slightly different) code for this, or tweaked an existing shell.

The original UNIX system was used mainly for text processing. In this context, small programs were an adequate substitute for shared libraries (and easier to implement). Gradually this little hack became a tradition, and the original reasons for it were overlooked.

If UNIX had started off with shared libraries from the start, things might have been quite different.

8. You advocate message passing microkernels, but aren’t they really expensive?

Scalable is the new fast. A few years ago, you just had to wait a little while and you could buy a CPU that ran twice as fast. Now if you wait, you will get one that’s about the same speed but does twice as many things at once.

The most recent developments have dramatically changed the costs associated with microkernels. Context switches are traditionally expensive. Anyone who grew up on x86 machines will be familiar with the idea that you have time to go and get a cup of coffee while a context switch takes place. And I’m not talking about instant coffee. For people who are more used to RISC platforms, a context switch has slightly more overhead than a function call.

It used to be that a monolithic kernel needed two context switches for a system call: one into the kernel and one back. A microkernel needed four: one into the kernel, one out of the kernel and into the server handling the call, then two going back the other way. QNX showed that this didn’t have to be the case. If your system calls were asynchronous, then you could batch a few of them up and perform several in a single set of context switches.

SMT and multiple cores change the rules slightly further. With SMT (or HyperThreading, as Intel calls it), the cost of switching between two processes on virtual processors on the same core became almost zero; you don’t need to save the state to memory; you just flip a switch and use the other set of registers for a bit. If the kernel lives in one context and user-space process in another, then switching between the two is very fast.

The second part of the puzzle is provided by multiple cores. If each server in a microkernel system is already running in its own core, then the cost of switching to it is dramatically reduced. Add in a kernel thread that scans every process’s address space for queued messages and moves them around asynchronously, and you can get away without any context switches.

This sounds expensive, because it involves a lot of polling. It can, however, be combined effectively with the power-saving features on modern chips. When a process realizes it is spending a lot of time polling, it can throttle the core it is running on to a lower clock speed.

The ideas outlined here are just one potential approach to making microkernels more efficient. For a taste of how scalable asynchronous programming can be, try playing with Erlang and get used to the feeling that you can make your code faster by throwing another few dozen cluster nodes at it. Remember too that a few dozen cores in a laptop will be common in a few years. If you think Erlang—a dynamic, asynchronous message passing language—is slow, then take a look at the benchmarks that show Yaws (an Erlang web server) handling 20 times as many connections as Apache. Then remember that Yaws scales better to more parallel hardware...

9. With what do you propose we replace UNIX?

At the moment? UNIX. Currently, UNIX-like systems are the least-bad choices. All the operating systems I use regularly are UNIX-based. If OpenVMS were open-sourced and ported to platforms that mere mortals can afford, then it might be an interesting choice as well, but I doubt that will happen.

The important thing is not to be satisfied with current, lackluster offerings. As soon as you start believing the system you are using is perfect, it will stop improving.

800 East 96th Street, Indianapolis, Indiana 46240