More Experience with MINIX in an Operating Systems Lab

4 downloads 0 Views 194KB Size Report
of the Apple Macintosh version of MINIX, a UNIX look-alike operating system available ... These tasks accept requests for service in the form of messages ..... the C language run-time library and several kernel tables to support some new system calls. ... Implement a new system call filock(fd) that takes a le descriptor fd as its ...
More Experience with MINIX in an Operating Systems Lab Stephen J. Hartley Math and Computer Science Department Drexel University Philadelphia, PA 19104 (215) 895-2678 [email protected]

Abstract

In operating systems classes, students study the theory, concepts, and mechanisms of operating systems: system calls, layered design, the client-server model, processes, interprocess communication, CPU scheduling, deadlock, input and output, device drivers, memory management, le systems, protection, etc. Their understanding of these concepts will be enhanced if they are given the opportunity to examine the internal operation and source code of an actual operating system and see how the various concepts and features studied are implemented. By modifying the source code to change the behavior of the operating system or introduce new features, students can further enhance their understanding and gain valuable practical experience. This paper describes the use of the Apple Macintosh version of MINIX, a UNIX look-alike operating system available in source form, in an operating systems workshop course. The use of the Macintosh version is compared to the IBM PC version. What the students learned from the workshop assignments is discussed.

1 Introduction Tanenbaum's operating systems textbook [8] uses a UNIX look-alike operating system for the IBM PC, called MINIX, as its primary case study. The source code (C language with some assembler) for most of the MINIX system is listed in an appendix of the book. The entire MINIX system, including a C compiler, is available from the publisher for a variety of machines, including the IBM PC, XT, AT, PS/2, 386, and most compatibles, the Apple Macintosh, the Atari ST, the Commodore Amiga, and the Sun SPARCStation. More details about hardware requirements and how to obtain MINIX can be found in the articles \MINIX Information Sheet" and \MINIX Frequently Asked Questions" posted regularly to the USENET newsgroup comp.os.minix. A recent article [2] describes the use of the IBM PC version of MINIX in an operating systems laboratory course at the University of Vermont. See that paper for more detailed information about the history of MINIX, its internal structure and operation, and the lab projects given to the students. This paper describes MacMINIX, the Macintosh version of MINIX, and its use in a similar operating systems workshop course at Drexel University. MINIX is designed using the \minimal kernel" and client-server approach. The kernel handles process scheduling, context switching, hardware and software interrupts, and message passing. Running as separate processes and in user CPU mode are two servers or daemons, the memory manager MM and the le system manager FS. These servers accept requests in the form of messages from user processes for memory (e.g. fork system call) and le operations (e.g. open, read, write, etc.). Running within the kernel's address space and in supervisor CPU mode are device tasks acting as device drivers, one per device type. These tasks accept requests for service in the form of messages from the two server daemons. The two server daemons handle all system calls from user processes. For example, a user process reading from a le sends a message to FS, asking FS to place the next so-many bytes from the le in a speci ed memory bu er in the user's address space. FS gures out which device contains the le and if the blocks from the device containing the requested bytes are already in the block bu er cache in memory. If so, the bytes can be copied to the user's bu er; if not, FS sends a message to the device task and waits for that task to copy the blocks from the device into the block bu er cache. The device task formats a request to the device  UNIX

is a Registered Trademark of UNIX Systems Laboratories.

1

controller and waits for a message from the kernel. The controller will use the system bus to copy the blocks from the device into memory and then generate an interrupt. The kernel will turn this hardware interrupt into a message for the device task, unblocking it. The device task now sends a message to FS, unblocking it so it can complete the user's read request. In operating systems classes, students study the theory, concepts, and mechanisms of operating systems: system calls, layered design, the client-server model, processes, interprocess communication, CPU scheduling, deadlock, input and output, device drivers, memory management, le systems, protection, etc. Their understanding of these concepts will be enhanced if they are given the opportunity to examine the internal operation and source code of an actual operating system, such as MINIX, and see how the various concepts and features they studied are implemented. By modifying the MINIX source code to change its behavior or introduce new features, students can further enhance their understanding and gain valuable, practical, \hands on" experience. This article describes MacMINIX, the Apple Macintosh version of MINIX, and its use in an operating systems workshop or laboratory course at Drexel University. Particular attention is paid to the di erences between the IBM PC and Macintosh versions and the e ect these di erences have on laboratory set-up and programming assignments.

2 MacMINIX The Macintosh version of MINIX [7] runs as an application under MacOS, in contrast to the IBM PC version which runs as the native operating system directly on the hardware. The MacMINIX system consists of three Macintosh les: an application le, named MacBoot, which contains the kernel (interrupt handlers, device drivers, and CPU scheduler), the memory manager, and the le system manager; a le about half a megabyte in size containing the MINIX root le system; and a ten megabyte le containing the MINIX /usr le system. After booting a Macintosh, the user can start MacMINIX by double-clicking on the MacBoot application le. In a few seconds, two windows will appear on the screen, each with the usual UNIX \login:" message, along with a new menu bar. MacMINIX allows true multitasking. A logged-in user can start several processes and they will execute concurrently, sharing the CPU. As far as MacOS is concerned, this is all happening within the application on which the user double-clicked. The version of MacMINIX distributed by Prentice Hall is 1.5.10. This version runs without problem on MacOS System 6. To run MacMINIX under System 7 and Multi nder without frequent crashing, one must obtain a set of patches that bring MacMINIX up to version 1.5.10.7 and recompile the a ected les. These patches are available by anonymous ftp from site plains.nodak.edu in directory pub/Minix/ftp-contrib/mcminix. The major di erence between the IBM PC version and the Macintosh version of MINIX is in the device drivers for the oppy, the hard disk, the keyboard, and the screen ( les floppy.c, wini.c, keyboard.c, and console.c in the directory /usr/src/kernel). The IBM PC version device drivers are for the actual hardware; the disk drivers contain code to do seeks, to start and stop the oppy drive motor, to set up DMA, etc. On the Macintosh, these drivers just set up calls to the ROM \toolbox" routines that do the real work. Similarly the MacMINIX console driver interfaces with the toolbox windowing routines. Another di erence involves the contrasting memory organizations on the Intel 8088 and successor chips (IBM PC) and the Motorola 68000 and successor chips (Macintosh). The Intel chips use a segmented memory organization. Each process has several segment registers that point to the base addresses of areas of memory containing the code, data, and stack for the process. The addresses generated by the CPU to load instructions and load and store data as the process runs are o sets into the appropriate segment and are added to the appropriate segment register to get the actual physical address of the item in memory. The Motorola chips use a at addressing scheme in which the process occupies a single contiguous area of memory instead of several segments. The addresses generated by the CPU are actual physical memory addresses. This has major implications for the implementation of the fork system call in MINIX. In the IBM PC version, fork is implemented by copying the segments of the forking process to new areas of memory for the child process and adjusting the segment registers of the child to re ect where in memory it will be executing. Copying the forking process to a new area of memory to create the child will not work in MacMINIX because the addresses in the child's code would be into the address space of the parent. Instead the shadowing technique is used. When a process forks in MacMINIX, the parent is copied to another area of memory and suspended. The child is allowed to execute for a few time quanta in the memory that was occupied by the parent. If the child has not done an exec system call, then the parent and child are ipped or swapped and the parent is allowed to execute in its original area of memory for a few time quanta. This ipping is continued until the child executes the exec system call, exits, or is killed. This 2

Assignment Spring 1992 Spring 1993 C Warm-Up Programming x x Recompiling the System x Counting Messages Sent x Round-Robin Time Quantum x CPU IO-Bound Scheduling x Terminal Driver Word Erase x x Adding Semaphores x Adding File Locking x x Adding User-Level Message Passing x Figure 1: Programming Assignments. scheme usually works well because most fork system calls are followed very quickly by exec system calls in the child process.

3 Laboratory Environment The operating systems workshop course met twice a week, 90 minutes each time, for 10 weeks (Drexel is on the quarter system) during the spring 1992 and spring 1993 quarters. About a dozen students were registered each quarter, including several graduate students. Class time was used to answer student questions, to trace through the MINIX source code, and to discuss possible approaches to the programming assignments. All projects were done individually by the students. The Macintosh Laboratory used for this workshop contained 15 Mac IIci machines. Each had 5 megabytes of main memory, an 80 megabyte internal hard disk, and ran System 7.0.1. The hard disk was partitioned into a 50 megabyte locked storage area, containing system software and the MacMINIX folder, and a 30 megabyte workspace. Students wishing to use MacMINIX rst copy its folder from the storage partition into the workspace partition and then double-click on the workspace copy of the MacBoot le. The slight inconvenience of copying assures that a user gets an original unmodi ed copy of MacMINIX with which to work. Students keep their own MINIX les on 3.5 inch oppy disks. A MacOS le containing a MINIX le system can be created on a oppy disk and attached to the MINIX le system hierarchy with the mount command. Students have to remember for two reasons to copy to their mounted disks any changes they have made to the MINIX source code. First, they need to access their changes from any Macintosh they later run MINIX on, and second, all changes to the workspace copy of MINIX are lost when the workspace is cleared.

4 Lab Assignments The article [2] describes several lab projects that were assigned: recompiling the kernel, MM, and FS; xing a serious bug in the MINIX 1.1 C runtime library libc.a; removing the restriction that a user process can send a message only to FS and MM and thereby allowing synchronous message passing between user processes; instrumenting the kernel so that when function key F4 is pressed, a count of all messages sent and received is printed on the console window; changing the CPU scheduler so it is preemptive and gives higher priority to IO-bound user processes; modifying the terminal device driver so that control-W will erase the previous word typed by the user; implementing memory compaction in MM; and adding named pipes, le locking, and symbolic links to FS. During the Drexel operating system workshops, six lab projects were given. There was some overlap with the ones described above. For the most part, students worked on these assignments on their own time whenever the Macintosh Lab was open. Sometimes students were given the last 20 minutes of class time to work on their assignments so they could ask questions or show any problems they were having to the instructor. Figure 1 shows the assignments given during the two terms the workshop has been o ered at Drexel.

3

4.1 C Warm-Up Programming

The rst assignment consisted of writing three C language programs that used such UNIX C library routines and system calls as getc, putc, fork, execl, pipe, creat, open, close, dup, exit, setjmp, longjmp, getpid, alarm, read, write, kill, and signal. This assignment gave the students experience using MacMINIX and practice writing C programs, as well as reinforcing their understanding of the operating system services, the version 7 UNIX system calls, provided by MINIX. It is essential that the students understand how these system calls work because later assignments may modify how a system call works or add support for new system calls.

4.2 Recompiling the System

The next assignment was to learn how to recompile all of the source code of the three MINIX components: the kernel, the memory manager, and the le system manager. Students became familiar with the make command. It takes ve to 15 minutes to recompile the three components, much less than the hour it took to recompile MINIX 1.1 on a dual- oppy IBM PC reported in [2]. After completing this assignment, the students were ready to modify and recompile the system for later assignments. Instead of just recompiling the system, the spring 1993 students did Exercise 31 on page 109 of [8]. This involved adding a few lines of code to the kernel to keep track of how many messages have been sent from one process to another. These counts were appended to the information dumped to tty0 when the Procs entry of the Debug menu was selected. It is essential that the students become comfortable with recompiling the system because they will be doing it many times in later assignments.

4.3 Round-Robin Time Quantum

The next assignment for spring 1992 was more of an experiment. The students had to nd where in the MINIX code the round-robin time quantum (100 milliseconds) for CPU scheduling was set. Then they had to try some smaller and larger values to determine the e ects on system overhead, throughput, and response time. They had to construct a shell script and a collection of programs that when run would give them some way to measure interactive response time and CPU context switching overhead. One problem encountered was that the time quantum could not be set smaller than 16 milliseconds, making it dicult to create a high context-switching overhead situation. A large context-switch time did, however, have a noticeable negative e ect on interactive response time. This assignment gave students practice in the scienti c method: formulating an hypothesis about what e ect the time quantum size would have on system performance and then devising experiments to test that hypothesis. Students have read in the textbook that a large time quantum increases throughput or system eciency at the expense of interactive response time, and a small time quantum decreases response time an the expense of system overhead. This lab shows these things actually happening.

4.4 CPU IO-Bound Scheduling

The next assignment for spring 1993 consisted of doing Exercise 32 on page 109 of [8]. It was also of the nature of an experiment. Students had to construct an experiment in which several CPU-bound and IO-bound processes were running concurrently. They had to modify the CPU scheduling code in the kernel to give priority to IObound processes and then measure system throughput to see if their CPU scheduling modi cations resulted in an improvement. This assignment also gave the students an opportunity to x a bug in the MINIX CPU scheduling algorithm [9]. An excerpt from the assignment follows. As it is, MINIX makes no distinction between processes that are IO-bound and those that are CPUbound. An example IO-bound process is one reading a le, doing a little processing, and writing to another le. An example CPU-bound process is one inverting large matrices of double-precision oating point numbers. Better system performance and throughput would be obtained, in theory at least, if IO-bound processes were given a higher scheduling priority for the CPU. This would tend to keep the IO-devices busy while the matrices were being inverted. An IO-bound job will consistently use a small percentage of its time quanta, whereas a CPU-bound job will use all of its time quanta. 4

By examining sched_ticks in clock.c, you can keep track of the percentage of its most recent time quantum a user process is using before relinquishing the CPU due to its time slice expiring (CPU-bound) or its making a system call and blocking (IO-bound). Add another eld, p_ticks_used, to the process table slot for each process. At each clock tick, do p_ticks_used++ for the process that was executing on the CPU just before the clock interrupt. Keep the user ready queue USER_Q ordered from low to high values of p_ticks_used when it is manipulated by ready(). In other words, if a user process only used a few ticks of its time quantum the last time it ran on the CPU, then give it a higher priority for another shot at the CPU by placing it towards the front of the user ready queue.

4.5 Terminal Driver Word Erase

The next assignment for both terms was to modify the terminal device driver so that typing control-W would erase the last word typed on the command line, much like control-H erases the last character typed (Exercise 37 on page 190 of [8]). The students must rst nd where in the terminal driver code a typed character is checked to see if it is the character-erase character. Then they can add code to check for the word-erase character and use the code that erases the last typed character from the screen as a guide for code to erase the last word typed. Finally, the students must add code to the terminal driver initialization for the default word-erase character. For this assignment, the students have to look at device driver code, gure out how it works, and then modify it to add the new feature.

4.6 Adding Semaphores

The next assignment for spring 1992 was the most dicult and time consuming for those students and involved adding semaphores to MINIX, speci cally the memory manager module /usr/src/mm. This assignment involved modifying the C language run-time library and several kernel tables to support some new system calls. Most modi cations were to the memory manager, which handles the new system calls. An excerpt from the assignment follows. Implement ten semaphores, all initialized to zero when the system is booted. Implement P and V operations on them (called down and up in [8]). Pick new system call numbers for the P and V system calls and add them to /usr/include/minix/callnr.h, /usr/src/mm/table.c, and /usr/src/fs/table.c. Add new library routines P(i) and V(i) to the C run-time library /usr/lib/libc.a so that the library routines will be loaded automatically when user C programs reference them, just as happens for printf, etc. Look at the code in /usr/src/lib/posix/setuid.c to see how to code a library routine that implements a system call. The ar command is what is needed to add a new library routine to libc.a. Calling P(i), 0  i < 10, from a user C program will ask the memory manager to decrement the ith semaphore if it is greater than zero, else block and queue the process. Calling V(i) will increment the ith semaphore if the queue of processes blocked on it is empty, else pick a process ( rst-in- rst-out queueing for fairness) from the queue to unblock. If calling P(i) results in a process being queued and blocked, then the memory manager defers replying to the P system call made by the process. If calling V(i) results in a process being dequeued and unblocked, then the memory manager is nally doing the reply to the earlier P whose reply was deferred, in addition to replying to the process that did the V. See do wait() in /usr/src/mm/forkexit.c for an example of how the memory manager defers until a later time replying to a process making the wait system call. A good way to handle the queueing is a scheme similar to the way the kernel queues processes that are trying to send a message to a process that is not waiting to receive a message (see page 103 of [8]). Add extra elds to each slot of the memory manager's process table /usr/src/mm/mproc.h for queue pointers. These NUM SEM semaphores (de ne this constant in /usr/src/mm/const.h, default value ten) are available to any and all processes for all time after the system is booted. The only time they are initialized (to zero) is when the system is booted. Both P(i) and V(i) will return -1 if i is out of range. If a process that is blocked on a semaphore P operation gets a signal that would abort the process, then the process has to be removed from the semaphore blocked queue. This assignment requires a thorough understanding of many parts of the MINIX system: the C runtime library, the implementation of the system call mechanism in the kernel and MM and FS server daemons, how the kernel 5

queues processes blocked in sending a message, how system calls are carried out in the server daemons, and where to add new code implementing additional features. The student must also have a thorough understanding of the semaphore concept in order to add support for semaphores to an existing system. The students tested their implementation of semaphores with the dining philosophers program. Each fork is represented by a semaphore. A hungry philosopher must execute a P operation for each of the two forks it needs to eat. To prevent deadlock, one philosopher always tries to grab its forks in the opposite order from all the other philosophers. Testing their semaphore implementation this way reinforces their understanding of semaphores and the dining philosophers problem. With the addition of semaphores, MINIX becomes a system that can be used for programming semaphore versions of the many classical operating system synchronization problems (page 75 of [8]).

4.7 Adding File Locking

The last assignment for spring 1992 (next to last for spring 1993) was to add le locking to the le system (Exercise 35 on page 335 of [8]). This assignment turned out to be fairly easy to do for the spring 1992 students since they had already done the semaphore assignment. Many of the same things needed to be done to the le system manager as were done to the memory manager. It would have been better for this assignment to precede the semaphore assignment, but the le system material in the text [8] follows the memory management material. For this reason the spring 1993 students skipped the semaphore assignment and went right to the le locking assignment. An excerpt from the assignment follows. Implement a new system call filock(fd) that takes a le descriptor fd as its argument and locks the corresponding le. Also implement a new system call unfilock(fd) that unlocks the le corresponding to the le descriptor argument fd passed to it. File locking is advisory and the lock is on the i-node ( le), not a le descriptor number. If the le is already locked, the system call fails. A user program can open a le already locked (by some other process), but it cannot lock the le until the other process unlocks the le. A programmer would typically code the sequence fd = open(file_name_string, ...); ... while (filock(fd) < 0) sleep(60);

This assignment gives the students more practice with implementing new system calls, this time in FS rather than MM. They also have to devise tests for the correct operation of the new features and learn how to evaluate their testing.

4.8 User-Level Message Passing

This was the most dicult assignment for the spring 1993 students. Fortunately they had already had practice adding new system calls to MINIX. An excerpt from the assignment follows. Alter MacMINIX, speci cally the memory manager daemon, so that user processes (USER_Q) can do synchronous (blocking) message passing (usend() and ureceive()). This is to be completely distinct from the message passing (send() and receive()) done between device driver tasks and the two daemons or between a user process and one of the two daemons, and implemented in the kernel where the source and destination are speci ed with process table slot numbers. Pick new system call numbers for usend() and ureceive() and have those system calls handled by the memory manager. Add library routines usend() and ureceive() to the C run-time library /usr/lib/libc.a. They are used as follows. To send a message to another process, do a usend(int pid, int message) where pid is the process id of the recipient. To receive a message from a speci c process, do a ureceive(int pid, (int *) message) where the integer message will be placed at the address given by the second argument. To receive a message from anybody, do a ureceive(ANY_USER, (int *) message) where ANY_USER is a prede ned constant (0 or -1). If a usend() results in the sender process being queued and blocked due to no matching ureceive(), then the memory manager defers replying to the usend() system call made by the sender process. If a ureceive() results in a sender nally being dequeued and unblocked, then the memory manager is nally doing the reply to the earlier usend() that was deferred, in addition to replying to the process that did the ureceive(). See do_wait() in /usr/src/mm/forkexit.c for an example of how the memory manager defers replying to a process making the wait system call until a later time. A good way to handle the queueing is a scheme similar to the way the kernel queues processes that are trying to send a message 6

to a process that is not waiting to receive a message (see page 103 of [8]). Add extra elds to each slot of the memory manager's process table for queue pointers to the rst and subsequent blocked senders. Return the message passed by the sender as a second result (see reply() in /usr/src/mm/main.c) and have your ureceive.c routine in /usr/src/lib/posix store that second result in the message address in the same way that wait.c does in /usr/src/lib/posix. If the sender queues on the receiver waiting for the receiver to execute ureceive() and if the receiver exits or is killed by a signal before executing ureceive(), then have usend() return -1 to the sender and set errno to EGONE. Similarly, if a process blocks waiting to receive a message and the process it wants to receive from exits or is killed by a signal, then the ureceive() returns -1 and errno is set to EGONE. If a blocked sender is killed by a signal, then the memory manager will have to search the process table to nd where the sender was queued. See, for example, do_xit() in system.c. If a process blocked on either a usend or ureceive system call gets a signal for which it has a handler set up, then the system call fails with errno set to EINTR, just as happens with the read system call. Both usend(pid, message) and ureceive(pid, &message) will return -1 if pid is out of range or does not match an existing process (set errno to EINVAL).

4.9 Debugging

There is no \debugger" for MacMINIX except the printf statement, which can be placed in the kernel, memory manager, and le system manager source code for debugging output. When MacMINIX is booted, two windows appear on the Macintosh screen, labeled tty0 and tty1. Debugging output shows up in the tty0 window. The user can log in to the tty1 window to avoid intermixing user program output with kernel debugging output. The MacMINIX menu bar has two useful entries: Windows and Debug. The former can be used to rotate window focus and change fonts and point sizes; the latter can be used to dump the process table and memory map to tty0.

4.10 Macintosh versus IBM PC version

As mentioned above, the major di erences between the IBM PC version and the Macintosh version of MINIX, in terms of the source code and how it a ects programming assignments, is in the device drivers for the oppy disk, the hard disk, the keyboard, and the screen, and in the implementation of fork system call due to the di erent memory addressing schemes of the microprocessors. This will have a major impact on programming assignments involving devices, for example Exercises 33-35 on page 190 of [8]. It also means that memory compaction is not possible in MacMINIX and cannot be used as a programming assignment, as it was in [2]. A MacMINIX process can only execute in the area of physical memory originally allocated to it; the process cannot be moved once it has begun executing. In addition, the use of shadowing to implement fork makes CPU scheduling and programming assignments involving CPU scheduling more complicated. In spite of these disadvantages, the Macintosh and MacMINIX do have some advantages compared to the IBM PC version when used in an operating systems workshop.  The ability to divide the Macintosh hard disk into a locked storage partition and a workspace area means that MacMINIX can be stored in the locked area, where it cannot be changed by students. When they want to use MacMINIX, particularly to make modi cations as part of an assignment, they make a workspace copy to use.  Since MacMINIX runs as an application under Multi nder along with whatever other applications are running, a crash of MacMINIX usually has a less severe impact that if it were running native on the bare hardware.  While a compile of the whole MacMINIX system is being done, students can use a communications package like NCSA Telnet to log into another machine and read their electronic mail or work on other assignments, etc.  On the IBM PC, students have to build a new boot disk in order to test a new version of the kernel as part of an assignment, then reboot the machine with the new boot disk. On the Macintosh, a recompile of MacMINIX creates a new application named NEWmacboot in the current folder. To test the new kernel a student need only quit the current application and double click on NEWmacboot. This takes much less time.

7

5 Alternative Approaches for OS Labs There are other approaches to providing practical learning experiences for students: computer and operating system simulators [3, 6], and small operating system kernels running on the hardware [4, 5]. Nachosy [1] is a very simple, but functional, operating system for emulated hardware consisting of a network of MIPS-like workstations. In a series of projects, students design and implement improvements to the functionality and performance of the major components of Nachos. The C++ language is used and the project must be done on a MIPS-based workstation, such as a DECstation, since the native compiler is used. Support for SPARC-based workstations was added in September 1993. The Appendix of [6] describes a project for a machine-independent simulator for process scheduling, memory management, and process synchronization. The simulator randomly generates a stream of jobs with random characteristics making random resource requests. The OSP environment [3] contains a special module that provides a virtual machine by simulating the hardware of a simple computer. It also simulates a collection of concurrently executing processes generating requests that need operating system service. Students write various modules for the operating system that interface with others provided in binary form by the instructor to form a complete system. KMOS, kernel of a multitasking operating system [5], is a project that implements on an IBM PC the design speci ed in detail in the text. The kernel supports interprocess communication and synchronization, interrupt management, and process management. It is not a complete operating system, but can be used for embedded realtime systems. The MPX-PC project described in [4] is similar and runs \under" MS-DOS for le system support. There are advantages and disadvantages of these di erent approaches, the MINIX approach versus the simulator or small kernel approach. Simulators and small kernels give the student the chance to write di erent modules of the operating system from scratch. Lane and Mooney say in [4] that students learn much more implementing a small OS rather than studying and modifying or enhancing a larger OS. This assertion can only be validated with a controlled study. The projects described in this paper have been used in the classroom and the feedback is that the students gained valuable, practical systems programming experience with a complete working actual operating system. In the words of one of the graduate students at the end of the spring 1993 o ering, \I think the hand-on experience in this class is what really makes it worthwhile. Having taken the Operating Systems I and II courses, there is not too much that is new material but the experience of using the concepts in MINIX was great. I think this class should be taken by all computer science students. I know from work experience that many recent college graduates get their rst job in a maintenance environment. This class is excellent preparation: hunting through the MINIX code trying to nd out how things are done and how to implement new features are things that too many people never do as college students."

6 Conclusions MINIX is a complete, stand-alone operating system that comes with source code. Therefore it can be modi ed or enhanced in any way the user desires. Since it includes a C compiler, MINIX can serve as its own development platform. It supports nearly all of the version 7 UNIX system calls and includes nearly all of the standard utilities familiar to UNIX users and programmers. For these reasons it is an excellent environment for an operating systems workshop or laboratory. For several years, Drexel University has required students to buy or have access to a Macintosh computer. There are some 10,000 on campus. The availability of a Macintosh version of the MINIX software gives students with access to a Macintosh the opportunity to gain valuable, practical, systems programming experience working with the internal operations of an actual operating system. The semaphore and user-level message passing assignments in particular were good projects because of the many di erent parts of MINIX that had to be understood and modi ed, with the changes integrated together, to get all aspects of the assignment working correctly.

References [1] W. A. Christopher, S. J. Procter, and T.E. Anderson, \The Nachos Instructional Operating System," Proc. 1993 Winter USENIX Conference, January 1993, pp. 479-488. y Available by

anonymous ftp from ftp.cs.berkeley.edu in directory ucb/nachos.

8

[2] Stephen. J. Hartley, \Experience with MINIX in an Operating Systems Lab," ACM SIGCSE Bulletin, Vol. 22, No. 3, Sept. 1990. [3] Michael Kifer and Scott A. Smolka, OSP : An Environment for Operating System Projects. Reading, MA: Addison-Wesley, 1991. [4] Malcolm G. Lane and James D. Mooney, A Project Manual to Accompany A Practical Approach to Operating Systems. Boston, MA: Boyd & Fraser, 1988. [5] Milan Milenkovic, Operating Systems Concepts and Design, second edition. New York, NY: McGraw-Hill, 1992. [6] William A. Shay, Introduction to Operating Systems. New York, NY: Harper Collins, 1993. [7] Andrew S. Tanenbaum, Frans Meulenbrooks, Raymond Michiels, Jost Muller, Joseph Pickert, Steven Reiz, Johan W. Stevenson, MINIX 1.5 Reference Manual. Englewood Cli s, NJ: Prentice-Hall, 1991 (Macintosh version of the software). [8] Andrew S. Tanenbaum, Operating Systems: Design and Implementation. Englewood Cli s, NJ: Prentice-Hall, 1987. [9] R. Guerrero, L. Leguizamon, and R. Gallard, \Implementation and Evaluation of Alternative Process Schedulers in MINIX," ACM SIGOPS OSR, Vol. 27, No. 1, Jan. 1993.

9