You want to build a thread system? Experiment with an OS with memory protection and virtual memory? You want to do that without a lot of rebooting, Bochs/VMWaremagic and writing drivers? Well, then Nachos (Not Another Completely Heuristic Operating System) is for you. Nachos is an Operating System simulator. Hmm… . If you’re a bit like me, you’ll be wondering what in the world that is.
Overview
I have been very interested in OSes for years and have also been an avid OSNews reader, but I had never encountered this term (or Nachos in particular) before.
In Nachos’ case Operating System simulator simply means, that you can run an OS (a guest OS) on top of another one (the host OS).
If this sounds a little like Bochs/VMWare, then you’re right, because it works similar to them. It actually features emulation for
- a CPU (a MIPS CPU)
- a hard drive
- misc. stuff like an interrupt controller, timer,…
- etc.
which are there to run the Nachos userspace applications. That means that you can actually write programs for Nachos, compile them with a real compiler (an old gcc crosscompiler that produces code for MIPS) and run them. The Nachos kernel instead is compiled to the platform of the Host OS and thus runs natively on the Host OS’ CPU.
If you are not excited about this idea (or at least mildly interested), you have to consider what this means. People interested in OSes can easily experiment with high level matters like multiprogramming, VM organization and file systems rather than fiddling around with writing a bootloader (a task which has been tackled thousands of times by aspiring Torvaldses all over the world) first. Not to mention much easier debugging; if you want to output something from inside the Nachos kernel, just use a comfortable printf, instead of having to rely on your own console code (using BIOS, VGA,…) which might not always work reliably. Not to mention that you can easily log the debugging messages of your OS (for later thorough inspection) by simply redirecting stdout of Nachos to a file on your Host OS.
Don’t get me wrong, all these low level things are of course interesting too, and fiddling around with
bits, device control registers,… are be very educational (to learn how computers really work). But,
these tasks can also be very frustrating. With Nachos you can get a somewhat high level
overview of the task of writing an OS without all the tedious details. It could be argumented, that
the low level stuff helps to weed out the meek, and only leaves the best, hardcore bit fiddlers to
OS development. But I think approaches like Nachos make it easier to get the hang of OSes without
all the cruft; with the experience from the highlevel view, it might be easier for people to do the
low level parts.
Internals
After the basics, let’s now take a look at Nachos’ internals. Nachos was (/is) written with CS
students and Operating Systems 101 courses in mind. The source is prepared for several
assignments where different parts of the system can be explored and features implemented.
I won’t go into details about the source code and it’s organization, since there is a lot of very good
documentation about that on the web; I will instead explain some Nachos internals using the assignments.
Note: This article is concerned with Nachos 3.4, as this was the version I used in my
course.
Threads assignment
This assignment is included so people can get acquainted with the source.
Nachos isn’t much of an operating
system yet; actually it’s mostly just the implementation of a userspace thread library. To avoid confusion,
we are talking about userspace from the host OS’ point of view: at this moment, Nachos is nothing
but kernel, and this kernel is multithreaded. There is not much else in the compiled binary;
the MIPS emulation is running, but it is not used. One of the tasks (for which some stub code
is already contained in the source), is the implementation of the thread synchronization facilities
Lock and Condition Variable. The other part is to implement Join functionality (ie. one thread T1 can
request to be blocked until a thread T2 terminates).
Syscalls, Multiprogramming and Memory protection assignment
This is where it gets interesting and where important OS features are implemented.
For many of theses features, there are already code stubs in the Nachos source.
There is, eg. already a fully implemented syscall in there, complete with (MIPS) code
showing how to use it from the userspace.
There is also code for the memory protection code. A class implementing code necessary
for setting up an address space and reading an executable file is already in there. What you
have to add, though, is code to properly handle the page tables for the processes and the
processes own data, like file handles etc.
This is rather spread out over different places in the code. It starts with implementing an
EXEC syscall, goes on to implementing a process table and defining process states, and
doesn’t stop with work on the address space again (eg. where do you have to put what, to
allow your applications main()
function to access parameters passed in by
the EXEC syscall, ie. the argc and argv parameters. I found this rather interesting, since
you deal with these things daily, but don’t really know, how they actually work).
Virtual Memory and software-managed TLB
This assignment (the last I had to do in my course), is all about virtual memory. To be clear:
this concerns the whole swapping related parts of the memory system; ie. moving parts of the
memory from RAM to some backingstore on the systems hard disk (I mention this, since there
seems some confusion about the terms, since memory protection (with page tables,… etc.)
is also called virtual memory). There is nothing spectacular here, and no code is provided
by Nachos for this task.
The other part of this assignment is more interesting. In the previous assignment, memory protection
was implemented by use of page tables, ie. each address space had a page table in a specific
format, and at a context switch, the MIPS CPU was given a pointer to the current page table.
This is basically the method, that the x86 CPU uses. I was somewhat surprised, when I heard
about software-managed TLBs. I knew about TLBs but only in the x86 way, where they are just
a cache for the pagetable. On the x86, you don’t know about the TLB, and you actually can’t
explicitly modify it (you can only flush it using a trick, ie, changing the control register
that stores the address of the page table). Few (if any?) RISC CPUs use this approach, but
instead have a software managed TLB, where it’s the OS’ task to set the entries, and the CPU
never actually sees the page table. This approach means some considerable (not immense, but
not trivial either) change in the way the memory system works. Due to the limited size of
the TLB, the OS now has to implement the cache behaviour for the TLB (ie. the CPU needs the
page translation for page x but the TLB is full, which page translation entry can/should be thrown
out now, etc.).
Filesystem and Networks assignments
These are actually two assignments, but I haven’t done them, so I can’t talk much about them.
The file system interface is actually already available in the 2nd assignment, ie. you can use
the file system from the Nachos kernel and the userspace applications (by way of the syscall interface);
the reason is, that in that assignment, all calls to the file system are simply mapped to the
host OS’ filesystem. This is a rather useful approach, since it allows using the FS early on without
actually having to deal with sectors, cylinders etc., and if you have finished your own FS, just
one line in a Makefile has to be changed to let the kernel use it instead of the host OS’ FS.
Problems
Working with Nachos has certainly been an interesting experience… although some aspects of the
system are less than ideal.
- Code quality:
Nachos is written in C++ … kind of. This is not modern, high level C++, but actually your
grandfathers C++, basically C with classes. Nachos is a nice example of a software project
that uses an OOP language, but is not even remotely object oriented. To cut a long story short,
classes are only used to emulate namespaces (to avoid having to give function names prefixes,
as is customary in C) and as somewhat more convenient structs.
Neglect of OOP features isn’t the only problem with the source. There are some hacks
in the code that just seem out of place and just aren’t good style (I won’t go into
detail here, if you’re interested, get the code). - User space multithreading:
In the course of working through the assignments, you’ll turn Nachos into a preemptive OS.
After you’ve done that, you’ll certainly want to show of the capabilities of your OS,
for instance by having several applications output stuff at the same time (you know,
application A outputs “A”, application B outputs “B” which should get you a nice
output of something like “AABABABBBBAABABA”, depending on the implementation of your scheduler).
Cool. Until you try launching several applications from a shell (a sample shell is
provided). The problem? Well, a command line shell is basically just a process doing a
read()
call on STDIN. This call is blocking, meaning the application is
halted until this call returns (ie. when some data is entered). Now, in a preemptive OS,
this should not be a problem; a blocking app is simply not scheduled to run and other
apps get their share of CPU time, nothing special about that.
The problem is Nachos homegrown, userspace thread model. The downside of userspace threading
is that a blocking call to an OS syscall, blocks all threads in the process’
address space. As each process in Nachos is mapped to a Nachos thread, this means that a
blocking call (likeread()
) will block the whole system, ie. all processes.
This means, that you cannot have an interactive shell in Nachos to launch background
processes and that one application invoking a blocking call will halt the whole OS.
People have found ways to get around this situation, but they are only hacks and don’t solve
the real problem. (In case you’re wondering: the trick is to useselect()
for
all blocking I/O. You useselect()
in a loop and set a short timeout on the
operation. If the function returns, you either have data, in which case you’ll exit the loop;
if you don’t have any data, this means the timeout kicked in; you now callyield()
which tells the scheduler to let other threads work. When the thread gets control again,
you simply continue in the loop and callselect()
again).
Conclusion and References
Nachos is a great system for teaching OS technoloy. Its use of an emulated CPU allows very realistic
insights into the work of OS developers, while hiding some annoying low level details.
The future
Nachos is a rather old project and is in its second decade already. It shows its age, as I already mentioned,
in the Problems section of this text. Some of those problems might be solved by Nachos 5.0j, which is
a port of the C++ code to Java. One major advantage is that Nachos finally gets a 1:1 threading system
and does not have to rely on the crufty userspace threading model it has been using.
References
- Nachos’ Home. Here you can
find several versions of the Nachos distribution and all the documentation you’ll need. - Nachos 5.0j The
Java version of Nachos. - Mini Stdio for Nachos programs This is a small library including a version of printf() that can be used
with applications that run on the Nachos OS. This will come in handy, as using the normal
Write() syscalls is quite tedious. It might be somewhat buggy and/or incomplete, but it works.
About the Author:
“murphee (Werner Schuster) is a student at the TU Graz, Austria, where he dabbles in Software Engineering matters. His interests besides Operating Systems are anything concerning Java (mostly the Virtual Machine internals). Find his Weblog here.”
I am currently working on the Nachos File Systems assignment for CS 140, a Stanford Operating Systems course. It if a great coincidence to find a fellow Austrian writing about the same exact topic on my favorite OS website. Does the TU Graz use Nachos for its classes?
I have enjoyed working with Nachos, because it makes it possible to do these very large projects in only 10 weeks of school, and it is a good first step into the world of OS programming. I only wished that Stanford also taught another practical OS course that uses a “real” Operating System.
there page is dated 94 and most refrences are around the same time frame.. it’s 2004 … 10 years later, doesn’t this count as ‘outdated info’?
I had a graduate OS class once that tried to use this… and failed terribly. The code is old, unsupported on any modern system. I was able to find a precompiled binary for linux that some random student somewhere somehow hacked to get working. We ended up dropping the whole thing and had to write simulators from scratch. It also didnt help that my professor thought that there was good documentation for it and didnt do much research into actual use prior to introducing it.
If you’re interested in this stuff, you might want to check out Buenos http://www.niksula.hut.fi/~buenos/buenos.html They used to use Nachos in the operating systems project course http://www.cs.hut.fi/Opinnot/T-106.435/project/ here at my school Helsinki University of Technology too but I guess the staff didn’t feel quite comfortable with Nachos anymore due to the problems mentioned here so they wrote their own machine simulator (YAMS) and skeleton OS which (Buenos). Unfortunately there was not enough free time in my schedule for this spring to attend the course (only doing the lecturing course about operating systems at the moment, next year the project, perhaps) but they say Buenos is quite nice.
“Can NACHOS run on Windows?
————————–
No. Not at this time. We’re planning to port but it turned out harder than it appeared; now that Win95 (finally, a real OS from Microsoft!) is out, maybe we’ll try it again.”
Quite dated, indeed…
Error: ‘NACHOS’ Is not a valid Win32 application.
How do you use this ?
>It if a great coincidence to find a fellow Austrian writing
>about the same exact topic on my favorite OS website. Does
>the TU Graz use Nachos for its classes?
Yup, that’s where I got to know it. They’ve been using
it for at least a couple of years, and they don’t seem
to be changing that.
I like the realism that Nachos allows, even despite some
of the problem (crufty code, …).
I worked with Nachos in the Operating Systems Course at UCR (Universidad de Costa Rica) almost three years ago.
Terrible
I would say that there is enough documentation to get started with any of the proposed assignments, but it also helped that my teacher had worked with it previously, so he could answer many of our questions and already knew about the changes required to compile it (like 6 – 10 changes, including definining the boolean macros, a couple of missing inclides and some misc changes).
1994?
Well, may be it is not the most up to date code, but is simple enough for an OS introductory course. You can read the code and have a good overall knowledge in a couple of days or so working with. You have to remember that probably most students in that level probably learned how to code something just the semester before.
When Nachos was taught on my OS course the TA got it to work under Cygwin.
I’m a sophomore in undergrad CS and we are using Nachos for our “Intro Operating Systems” course (CS 202 here).
I think Nachos is a great project to learn OS concepts on. It’s true that some of the Nachos code is hackish (particularly with regards to not utilizing all OO features of C++, but still being a C++ program). The only bad thing about Nachos is that most of my class runs Windows, and Nachos only really runs well on Linux and Solaris. So, they end up having to use Putty to connect to a Solaris server we have here to do their development (which I assume sucks pretty bad because they don’t even get X11 forwarding!).
If you are running Linux and are used to seeing hackish code, Nachos is great. I disagree that not enough documentation exists. Thomas Narten wrote a “roadmap to Nachos” guide that gives LOTS of documentation. The comments are pretty clear, and even point out hackish lines. And the “Nachos Project Guides” that float around and have the standard “lab” assignments are pretty clear as well.
Overall, this course is turning out to be pretty challenging and time-consuming, but altogether worth it. If you plan on learning OS concepts on your own by using Nachos, I reccomend you also do a little research on the general concepts behind the implementation (for example, when implementing Locks and Conditional Variables, I’d google how Locks and Conditional Variables are implemented “in the abstract,” i.e. with pseudocode). We use an overpriced textbook called “Operating Systems Concepts,” so maybe if you could borrow that from the library you’d be okay.
GeekOS ( http://geekos.sf.net ) is preparing an educational release of their OS, which is supposedly aimed at university courses on operating systems. The code is well commented and builds on Linux/i386, FreeBSD, Windows, and Unix platforms.
Mmmmm…nachos.
Since Buenos itself is compiled to MIPS machine language and runs on top YAMS, you can’t use gdb the way you can with Nachos where the kernel and the machine are both parts of the same host platform process.
With Nachos you can just disable interrupts when you have a critical section. With Buenos, the excercises are done with 4 (simulated) CPUs, so you have to learn how the synchronization stuff works on a multi-CPU machine.
AT UC Berkeley, CS162, the OS Course, uses a java version of nachos. You might want to check that out. I think it only runs on java 1.1.3 though, and maybe even a modified version at that.
Jon
When I was picking around with operating systems a while ago, I used http://www.cs.utah.edu/flux/oskit/ it’s basically a real operating system but extremely modular so that you could easily, for example, implement just a file system. Last update in 2002, but last time I played with it, it worked perfectly. It also allows coding in a number of different languages inside the os. I didnt play with that but it sounds very cool.
I consider Buenos + Yams a fine replacement for Nachos. If you are interested to take a closer look, you should keep in mind it’s rather new and has some rough edges – there are actually couple hundred mostly very minor fixes that aren’t included in the distribution sources and documentation. There are also areas where it still lacks intended functionality, for instance symbolic kernel debugging.
Buenos and Yams are much more realistic than Nachos as a platform for introduction in kernel programming. The system isn’t a model of any physical machine, though. For simplicity, hardware devices are as simple as they can be (but yet realistic), and for instance, the system doesn’t model CPU caches (which can be complex issue to deal in SMP environment, and also excess burden to model in virtual machine). As a proof of practicality, I did port NetBSD on Yams before Buenos was actually written.