It's easy (and legitimate) to blame the failure of Hurd on poor design and management choices.
I think it's also instructive, though, to observe how no "better than Unix" project has really attained any success. Some of them have delivered more workable code than Hurd, but Plan 9, Inferno, Amoeba - none of them have really caught on.
Interestingly unix derivatives are now some of the most popular operating systems for modern devices, as iOS, Mac OS, and Android are unix/linux based.
"Although Mach is often mentioned as one of the earliest examples of a microkernel, not all versions of Mach are microkernels.
The project at Carnegie Mellon ran from 1985 to 1994, ending in apparent failure with Mach 3.0, which was finally a true microkernel.
Mach and its derivatives are in use in a number of commercial operating systems, … most notably Mac OS X using the XNU operating system kernel which incorporates an earlier (non-microkernel) Mach as a major component.
Neither Mac OS X nor FreeBSD maintain the microkernel structure pioneered in Mach."[0]
I was one of the last Mach people at CMU. The BSD emulation on Mach 3.0 was implemented by stubs that made IPCs to the BSD emulation server, which then made additional Mach API calls to implement the UNIX semantics. This design was generally half as fast as an in-kernel implementation (e.g. Mach 2.5 or a commercial UNIX kernel). In the mid-90's we figured out how to make up the performance gap by refactoring the BSD emulation to put some code in the same address space as each application (ie in the libc .so), which allowed you to avoid the RPC to the emulation server in most cases (eg http://dl.acm.org/citation.cfm?id=168639). So I don't think it's fair to say that microkernel implementations of UNIX are inherently slow; instead I would argue that the simpleminded approach to UNIX emulation was the real problem.
None of this technology made it into a mainstream Mach distribution because the band broke up: Rick Rashid and his staff and students went off to work at Microsoft Research. Brian Bershad took over the project and then moved to University of Washington. It was also becoming clear in the mid-90's that the OS didn't really matter much anymore, since the big money was being made in Internet applications. So most of the hackers who might have worked on new operating systems during this time ended up working on application servers and web apps instead.
Anonymous HN readers, why the downvotes? I feel like Mach's wikipedia page succinctly answers the parent's question and gives some interesting background. Am I crazy?
More specifically, OS X and iOS run what is essentially a fork of Mach 2.5, a version of Mach that came out before the BSD code was split out of the kernel into userspace (that happened in Mach 3).
A few "merges" (to use source control terminology) of newer Mach stuff into xnu (the OS X kernel), but the BSD-in-userspace stuff never came over.
Some of the Plan9 people comment on and off how backwards going back to Linux seems: all these warts they had fixed decades ago, back from the grave! But a bunch of them work at Google now, so have to use Linux, since Google doesn't use Plan9 systems.
Actually the mistake that set the project back the most was the opposite, from the article:
Stallman later admitted, “I take full responsibility for the technical decision to develop the GNU kernel based on Mach, a decision which seems to have been responsible for the slowness of the development. I thought using Mach would speed the work by saving us a large part of the job, but I was wrong.”
He made what he thought was a pragmatic choice that ended up being wrong, not the "perfect" kernel.
I think that this article underestimate the ability of Linus Torvalds to manage the Linux developers community. Leadership, dispute resolution, technical choices, compatibility or new features, and teven flamewars. It's very difficult to be a BDFL.
The idea is that if Linux were not available, the open source community would have been working in Hurd and not in Linux. But without Linus perhaps the community could not exist (new member leave after a few quarrels) or all the effort is lost in complete rewrites.
Can someone explain to me if the problem with Hurd was that the basic idea was impossible, or it was the way they went about it?
i.e. was it the relentless restarting of the project that was to blame, or did they keep restarting because every way they approached it turned out to be impossible?
They emphasised architectural elegance over short term practicality - ie do it right rather than do it quickly. The problem with operating systems is that you need to have a minimum set of working functionality in order for it to be somewhat useful to people not developing the operating system itself. You need a way of storing data, you need a reasonable number of commands to run, you need editors etc. On the hardware side there was immense turnover in the late eighties and nineties. Processor architectures soared and waned, it wasn't uncommon for cpu speeds to double, memory become increasingly cheaper, peripherals changed (mice, cdroms, floppies changed size, Zip drives, tape drives), popular hardware buses changed (ISA 8/16 bit, ADB, VLB, PCI, PCMCIA, USB, serial, parallel). Just keeping up without changing your operating system core functionality was a lot of work!
The GNU project tended to work very cathedral like, while Linux was very bazaar like. The latter meant people could support and update the kernel for their own devices ("crowdsourcing" in today's terminology). http://www.catb.org/esr/writings/homesteading/cathedral-baza...
To give you an idea of how many shortcuts Linux took, the way the original kernel worked was that it used a single large address space. Each process was slotted into 64MB of that address space. That left you with a maximum of 63 processes. A context switch just involved changing protections to enable the appropriate slot. This is far more lightweight than how Linux now and other operating systems do it with no such process limits and a far more heavyweight full address space switch. Back then it made Linux really fast at process switching. This is an example of "worse is better": http://en.wikipedia.org/wiki/Worse_is_better
What the detractors didn't realise is that the initial simplistic Linux implementation could evolve away the constraints, and were instead betting on up front "intelligent design".
Microkernels were an immensely popular idea in academia (Mach, Minix, …) when Hurd was begun; I don't think the fundamental problem with them — performance is horrible — had been made obvious yet. Microkernel design is probably a good idea, but the message passing overhead kills actual microkernel implementations.
I've heard the Windows NT kernel described as being designed like a microkernel architecture (separate modules with clear APIs), but with direct function calls instead of message passing. I don't know if the Linux/BSD kernels are much different — I've poked at all three, and at a high level they look very similar.
> I don't think the fundamental problem with them — performance is horrible — had been made obvious yet.
On the contrary, the idea that performance of microkernels is "horrible" is the current received wisdom, believed by the majority of programmers without critical examination, and based on very performance-poor early microkernel designs like Mach.
The truth is that modern microkernel designs like L4 can perform IPC over 20 times faster than Mach. Another important advance for microkernels are tagged TLBs which can alleviate the TLB misses that are usually incurred on every context switch.
Someday, hopefully not too far in the future, someone is going to write a modern, practical, and free microkernel-based OS that implements all of POSIX with performance the rivals Linux, but that offers a level of isolation and modularity that Linux could never offer. When that happens, a lot of people are going to scratch their heads and wonder why they believed the people who told them that microkernels are "fundamentally" slow.
I had hoped that HelenOS would become this (http://www.helenos.org/), but its lowest-layer ipc abstraction is async-based, which I think is a mistake. One of L4's innovations was to use sync IPC, which offers the highest possible performance and gets the kernel out of the business of queueing. You can always build async ipc on top of sync without loss of performance; this puts the queues in user-space which is where they belong (they're easier to account for this way).
I asked the HelenOS people why they decided to go this way, and this is their response (one of their points was "the L4's focus on performance is not that important these days", which I disagree with). http://www.mail-archive.com/helenos-devel@lists.modry.cz/msg...
What about minix 3? It implements all of POSIX, and it's a true microkernel. The kernel process is apparently only 4-5K LOC which I have been meaning to take a look through.
Their papers have pretty detailed performance measurements. I recall that they pass fixed-length messages between processes for efficiency (to avoid buffering). And they said it takes approximately 500ns to send a message on a 2.2GHz Athlon, which is in the neighborhood of a malloc().
I don't know how the overall performance is. Minix 3 appears to be targeted at lower end devices, e.g. they mentioned OLPC. I don't think they have things that you would want for servers, like multicore support. I don't think anyone uses it for those types of applications. But it does implement POSIX and it is a microkernel. And from what I gather the codebase is relatively modern -- they said it is related to Minix 2 in name only.
Microkernels could use some hardware optimizations... And most of those optimizations are good for virtual machines too, so they'll get done.
In due time, message passing kernels will get so much faster than interruption based ones that we'll ask ourselves why we used monolitical kernels all this time. (And somebody will have to explain that microkernels used to be slow, and this person will be met with skepticism.)
That said, the computers we had at the 80's and 90's were completely unfit for microkernels. Mach was about the best you could have by then.
(But all that discussion about microkernels is an irrelevant sideline. Linux got adopted because it was there, if it weren't we'd probably use some version of BSD instead.)
Because it gets you an immense amount of existing tools that you won't have to reimplement. You can get shells, compilers, and numerous utilities (eg cp, cat, tail, tar, zip, awk). Look at the list of what BusyBox includes to get an idea of the kind of functionality any system would need to get started. http://www.busybox.net/downloads/BusyBox.html
If you provide terminal emulation then you also get editors. If you implement ptrace then you get a debugger. If you provide networking then apps can display remotely (X).
Even if you are developing something unique for your operating system, using POSIX in that lets you perform some of the development and testing on other systems that already have working toolchains.
In short having POSIX saves a huge amount of time and effort. That doesn't preclude you from having other APIs around too. Don't underestimate the importance of having a functioning system while you replace or augment it with parts that are your unique value add.
Sure, but keep in mind that my ideal would also involve discarding most what a POSIX compatibility layer would get you. Why cleanroom a nifty kernel and then turn it into something that's almost exactly like what already exists? If you want Unix, you know where to find it, as the wag said.
The kernel doesn't have to support POSIX. You can do the emulation in user space. The only tricky part of POSIX is fork, but chances are you won't need that for compilers etc, just exec.
In any event don't confuse the journey (some POSIX compatibility in order to advantage of existing toolchains while building your new OS) for the destination (clean, elegant, new API, world changing, nifty) OS.
And if you are going to have command line tools in your OS, they will need an API and you may as well pick a useful subset of POSIX.
So at some point, you can just put the whole FOSS environment (Firefox, Gnome, Gimp, LibreOffice, etc) on top of your kernel. Porting all those programs is much more work than writing a POSIX compatibility layer.
> Someday, hopefully not too far in the future, someone is going to write a modern, practical, and free microkernel-based OS that implements all of POSIX with performance the rivals Linux, but that offers a level of isolation and modularity that Linux could never offer.
Why, when we already have VMs like Xen which are modern, practical, free, host guest OSes that run at full speed to provide whatever API the applications want, and provide a level of isolation and modularity microkernels never could?
I think that's a fair question, though I disagree that microkernels are somehow inherently less modular and isolated than hypervisors.
I should say, first of all, that when I said "that implements all of POSIX" I didn't mean that POSIX should be its native or only API, but just one API that is offered for compatibility with the incredible amount of existing code that targets it. I agree with your implied argument that POSIX is by no means the be-all, end-all user-space API.
But that said, I don't think that multiple OS's running under a hypervisor is the ideal way of promoting choice and diversity of APIs. First of all, there's a lot more software involved: a hypervisor, a dom0 OS, and a guest OS, just to run anything at all. Sure it works, but there's a lot to be said for a smaller and simpler base system.
When you take the hypervisor approach, every guest OS has to implement very tedious and hardware-dependent basic functionality like booting, context-switching, paging, interrupt handling, etc. instead of being able to use an API that provides these things. This is all not to mention drivers, which is one of Linux's biggest advantages over all competitors.
I see that Xen has a paravirtualization interface that can solve some of these problems, and indeed the more that the Xen<->GuestOS interface becomes like an API/ABI and less like hardware emulation, the more Xen starts to look like a microkernel. I don't know the details of how Xen's paravirtualization interface works (and couldn't find good docs on in in a quick search) so can't comment on the specifics of it.
Maybe Xen's paravirtualization will morph into what I have in mind. One litmus test would be: do I have to statically configure the amount of RAM that each guest OS is allocated? There's no need to do this for multiple processes under a single OS, but any approach that is based on hardware emulation has to decide up front how much RAM the "hardware" has available.
One thing that's interesting is that, while microkernels haven't really won, Xen-style paravirtualization, which in a way is an even more radical version of the de-monolithization idea [1], has taken over in a lot of niches, despite performance being an even bigger problem, especially without hardware assistance.
The problem it tries to bring up is that there is a subset of processes running in the Linux Kernel as either baked in functionality or KOs that can avoid context switches and IPC calls by being baked into the same executable.
In practice, you can share memory. In practice, a code base as large as Linux actually ends up having a lot of TLB flushing whenever it alternates between the very different sections of binary that dictate behaviors of the core kernel and devices.
It doesn't help that the self fulfilling prophecy is that by fine tuning a baked in service into Linux means that a lot less effort is made trying to make it an efficient interface.
I am obviously biased, I think microkernels are a good idea. I don't know if its unix or not, but I don't like having one binary that will inject itself with extra linkables when needed that manages every device, the network stack, the sound API, manages the filesystem, manages memory, and manages processor scheduling. Most of this stuff doesn't need the kernel mode special processor registers, in practice a well designed system shouldn't require anything more than a fixed memory page reference to the device that the kernel will handle mapping (I can't think of a way to build a kernel without virtual memory, virtual files, and virtual processing baked in at the ground level, and 2/3 of those really do require special processor permissions).
You might not be biased. It's hard to ignore Wombat demonstrating context-switching costs that are up to 30 times lower than native Linux.
The status quo of kernels is reminiscent of the status quo of programming languages in the 90s. Where people programmed in faster, static languages and looked down on dynamic ones. I wonder what we will think of monolithic kernels in 50 years from now.
EDIT: A binary injecting itself with multiple code (linkables) might not be bad. It's much like what a macro does to a program. You turn one flag on and the source gets populated with the appropriate code.
It is lack of a dynamic way of injecting it that can bite you. The inability to easily change what was injected.
I've read the same issues about performances and have always wondered how the QNX micro-kernel could power embedded devices (and the next BlackBerry). http://en.wikipedia.org/wiki/QNX
QnX is extremely low overhead, and gets a much more responsive system out of the same hardware than a linux based system. Linux simply doesn't do soft-realtime well, forget about hard realtime, even with the patches applied the granularity is terrible, and prioritization is worse.
Those are the things where a microkernel shines. Because realtime systems value responsiveness (and minimal latency) over raw throughput they look worse on paper, but in use they feel a lot more responsive.
In a nutshell, having 300 MB/s throughput for some system function with latency ranging from 2 ms to 100 ms vs having 200 MB/s with latency ranging from 2 ms to 5 ms will give a very strong edge to the slower system if there is some cut-off beyond which the latency becomes unacceptable (for instance, machine or process control).
Lower performance on paper does not always mean worse performance, it depends very much on which criteria are considered to be more important. And latency can be much more important than throughput.
Mac OS X' kernel is Xnu, http://en.wikipedia.org/wiki/Xnu , which is based on the Mach microkernel but with pieces and bits from FreeBSD bolted on, for a hybrid approach.
This XKCD[0] explains the issue with Hurd perfectly, more-or-less echoing the ideas rogerbinns expressed. Note the mouseover text, which makes the observation that the Hurd loop is the loop in which you "code right" and the Android loop is the loop in which you "code fast".
Not only was it perfectly possible, microkernels have been sold commercially for decades and are extremely popular in hard real time environments where you want to be able to pre-empt a driver as though it is just another user process (which they are!).
Linux had a working version when the FSF had a longterm vision. There is nothing impossible in their design and more complex systems such as Windows or Inferno/Plan9 exist. In the case of Windows imagine how many hours were spent in its design. When Linux came out it worked and everybody was shocked, Hurd was never able to do this.
Not very different, since we're basically doing microkernel-y things anyway using various kinds of virtualization.
It would probably be more elegant to just run Hurd or whatever instead of for example running multiple JVMs on top of multiple Linux instances on top of a hypervisor (yes, this happens), but them's the breaks.
Well, kind of but not really. Xen isn't really bare metal in any sense of the phrase. It's just at a similar (but different) level of abstraction. In an embedded system you will need to have device drivers, respond to hardware interrupts, etc. On Xen you make hypercalls.
So eLua and these projects are similar in, say, the same way that a typical RTOS is similar to running Linux on AWS. They both have kernels, but the environments are vastly different.
Microkernels are not harder to debug than monolithic kernels. I'd even say that they are easier to debug, much easier. (Personal experience in debugging both.)
The problem with microkernel-based OSes is, as Linus Torvarlds aptly put it, that they turn well understood memory-protection problems into not-so-well-studied IPC problems. (The actual quote is «They push the problem space into communication, which is actually a much bigger and fundamental problem than the small problem they are purporting to fix.»)
The microkernel is not the real problem here, the big issue is debugging faulty IPC sequences between the servers that implement the OS services. A problem that is almost non-existent in monolithic kernel.
HOWEVER, current monolithic kernels are facing growth problems now because of two aspect: we want fancy remote storage accessed as easily as local storage (do you want to mmap a file stored in a RAID setup implemented with SATA-over-ethernet disks?) and the fact that the process model is too leaky and so we need stronger containers like VMs (that are becoming as much leaky abstractions as the current processes). All these new features require communication between various components that were previously though and implemented as independent. This means that the IPC problems are now creeping into the world of monolithic kernels.
There were a number of microkernel efforts at Apple in the 80s and 90s.
- Pink (later known as the money-burning party Taligent) had a 'new kernel' that was message-passing. They spent a lot of time working on RPC efficiency.
- The Newton used a message-passing kernel. Not the most efficient thing in the world, but there was MMU support to do some interesting page sharing / fault dispatch policy stuff, so you could get IPC-like behavior with faults. Basically hobbled by a 20Mhz processor with minimal cache, and not very much RAM at all.
Btw, I didn't notice the Newton being very hard to debug (except that all of our debugging was printf, or you stared at the disassembled output of CFront).
The way you word it, (and from my personal bias) it seems like people kicked the can on getting IPC right down the road. I like how plan9 handled it - one socket layer to rule them all, call into other programs over sockets, and let the filesystem handle the translations. I think in this modern era of extreme hardware juice, this could easily work. And work better than what we have.
Then again, I think shared memory is a harder problem to solve than using IPC through some buffered file metric. The synchronization becomes a pain in the butt, even if you manage a smidgen more performance out of the ordeal, it isn't very reusable, so it is only a situational tool. I feel like module injection a la Linux should have been a situational tool as well (at best), but we ended up putting everything in the kernel, and we keep adding more (KMS, KVM, DMI2, etc).
Compared to say an SOA platform with 200 service endpoints, a database with about 2000 tables, integration with 15 other providers with XML, CSV, SFTP and some wierd shitty non standard binary protocol. All written entirely by the lowest bidder without unit tests because they knocked the budget up. Oh and with a toolchain which barely works and no VCS system past an old corrupt source safe database full of compiled DLLs which there is no source for any more.
I've done both and am currently stuck doing the latter - I'd rather poke one of my eyes out and debug a microkernel if I had a choice.
Absolute nonsense. Micro kernels are much easier to debug than macro-kernels.
The reasons are obvious to anybody that has spent more than an afternoon working with both, a microkernel is so small that the chances that your problem is in the kernel are minute compared to having your problem in user space. That means that all your luxury debug tools are available to debug the vast majority of your problems.
After the initial write the kernel code of a microkernel system is hardly ever touched. A good microkernel will limit itself to do the most limited subset that will still allow the system to function and will move everything else to regular processes.
Stallman, the FSF and the free software ideals would probably be much more widely known. Many (most?) users of GNU/Linux call the whole OS "Linux" and honestly think Torvalds started the whole endeavour.
The story mentions this. The industry had a working Linux and jumped on board. It is like how the industry jumped on C++, or x64, javascript, or unicode. The small imperfections in form of these tools didn't, at the time of their inception, justify the more massive immediate workload of trying to completely replace them with no backwards compatibility for something without the blemishes. Competitors weren't mature enough to step in, so the imperfect progressions of tried methods took the reigns rather than bolder, newer ideas, that meant shifting some of the inertia of the industry.
I think that might be one of the lesser appreciable legacies of 80s - 00s in software. We have tools that are now really showing their flaws but we built the empire on cracked bricks and the unstable foundations force us to throw more man hours and effort into keeping the whole thing standing than if we just started with a fresh foundation when the better alternatives presented themselves, even if they would have taken some more work.
I still really wonder where we would be if we had a C++ with a clean grammar and Python level readability. Where we didn't try to layer interpreters and JITs over convoluted C ABI compatibility.
I recommend the "STEPS Toward Expressive Computing Systems" reports for more current-day thoughts on OS redesign (available here http://www.vpri.org/html/writings.php )
Basically, by designing exactly the necessary language for each layer, they've reduced the code requirements to reach useful applications by multiple orders of magnitude.
I honestly wouldn't be surprised if the results of this project eventually creep into industry.
I would be surprised if the results of this project eventually creep into industry.
It sounds great to write vector and font rendering in a few hundred or thousand lines of code. On the other hand, others have been writing orders of magnitude more code in orders of magnitude more time. I cannot believe that has been due to a wrong choice of language or approach. I much more believe it comes from supporting real-world standards and requirements. Loading fonts from various formats, lots of configuration, supporting more and more of Unicode, doing all that optionally with hardware support. That is the tedious part. It is not about how to implement Bresenham's line algorithm most elegantly.
“My first choice was to take the BSD 4.4-Lite release and make a kernel. I knew the code, I knew how to do it. It is now perfectly obvious to me that this would have succeeded splendidly and the world would be a very different place today."
So true. It's unfortunate AT&T/Unix System Laboratories kept the BSD kernel code locked up in a lawsuit. Would have loved the article to have had a deeper insight into that as Stallman had already chosen to abandon Hurd by the time Linux came around.
It wasn't just that Linux was available, it was that BSD wasn't. It's too bad that the last few years have seen a decline in FreeBSD / other BSD OS's especially as it is an amazing operating system still light years ahead of GNU/Linux is many areas. Not to mention that it's one unified OS rather than hundreds of GNU/Linux distros.
One can only imagine what would have happened had the BSD code not been tied up in lawsuits. I bet they would have gone with the mature BSD kernel, leading to a better OS, and Linux would probably be a footnote in history if that.
Interesting how inferior technology wins a lot more than it loses. That said, I still love GNU/Linux. :)
> Not to mention that it's one unified OS rather than hundreds of GNU/Linux distros.
I admittedly haven't used any BSD enough to make a well informed opinion but I was under the impression that BSDs are fragmented at the OS level (i.e.: different kernels), while Linux is fragmented at the distribution level (i.e.: default collection of software, file-system layout, etc).
I imagine that, in addition to there being different kernel flavors there are also distribution level differences (e.g.: there are subtle differences between FreeBSD's rc.conf and NetBSD's) so I'm not sure which approach is better or worse, but I tend to lean on the "one kernel, several distributions" camp.
There is no OS level fragmentation. Sorry that makes no sense in the BSD world. FreeBSD is an OS. OpenBSD is an OS. etc. That's not fragmentation. They are different OS's. It's like saying there's fragmentation between Windows and OS X.
GNU/Linux is one OS with hundreds of distros. That's fragmentation.
> One can only imagine what would have happened had the BSD code not been tied up in >lawsuits. I bet they would have gone with the mature BSD kernel, leading to a better OS, and >Linux would probably be a footnote in history if that.
Likely. For myself, in 1993 I recall being totally underwhelmed with Windows 3.1 when I got my first 386 SX PC. I went looking for something better and came across some BSD derivatives and Linux. I knew that there were some vague legal issues with BSD, so I chose to download the 30 or so SLS floppies that made up a Linux "distribution" and I haven't looked back since.
It's not enough to build something that's better. You also need to sneak it in like a Trojan horse into a user's fortress. You can't easily launch a frontal attack on Linux.
One of the most valuable opportunities with mobile is that current technologies can become irrelevant. A big success for L4 is that it made it into mobile phones.
As someone who's in his 20s and first got interested in programming as a kid by trying[1] to install Linux on his 386... I don't know how to react to this.
On the other hand, it's ridiculous to think of how far things have come since then... people who complain about Linux usability and driver issues in 2012 really don't know what they missed!
The first IBM computer to use a 386 was iirc the ps/2 model 80. There were also some clones out in short order, most notably the Olivetti and the Apricot.
Clearly RMS wanted his idea of perfection, and almost 30 years on, perfection remains out of reach while "good enough" rules the world on Linux.
An important lesson to learn.