The second phase of Nachos is to implement system calls. As in the first assignment, we give you some of the code you need; your job is to complete the system and enhance it. This document first describes the features and files in Nachos that you need to focus on for this assignment.
This lab is very much linked to the next one (multiprogramming support in Nachos). Both of these labs are very challenging and we strongly encourage you to form teams of two.
Once you understand the relevant portions of Nachos,
read the remainder of this handout in its entirety before beginning your project.
In this assignment, you will implement system calls and exception
handling for Nachos. You will
be working with the simulated CPU that is
provided by Nachos. We use a simulated CPU, because we want complete
control over how many instructions are executed at a time, how the
address spaces work, and how interrupts and exceptions (including
system calls) are handled. The Nachos CPU simulates a MIPS chip. The
simulator can run normal
C programs (except that floating point operations are not supported
and the only system calls supported are the ones that you implement).
At
present, Nachos is a uniprogramming operating system; it can run a
single C program at a time. As
a test case, we've provided you with a trivial user program,
See the Makefile
in the `test' subdirectory for an example of how to generate an
executable program for Nachos. Among other things, this
Makefile can generate the executable for
You will be working mostly in the
Understanding the Nachos Software, Part II
Before attempting to understand this assignment, you must first
understand the parts of Nachos that you will need to work with. Read
the following material before attempting to understand the assignment:
halt; all halt does is to turn around and
ask the operating system to shut the machine down. Run the program
nachos -x ../test/halt
from the userprog
directory. As before, trace what happens as the user program gets
loaded, runs, and invokes a system call.halt. Briefly,
C programs are compiled and linked using gcc and gld (with special
flags) and are then converted to Nachos object file format (noff)
using coff2noff, a utility provided by Nachos. Since
Nachos runs ordinary C programs, you can make your own test programs
that make the system calls you are implementing. Remember that you
cannot use system calls or library routines that use system calls in
your test programs. This means you cannot put printf statements in
your test programs, for example.userprog
directory. You must become familiar with the following Nachos files:
(found in the userprog directory)
userprog directory)
ExceptionHandler is called.userprog directory)
filesys directory)
machine directory)
machine directory)
threads directory)
Initialize method in
system.cc.
Your system call implementations should check the parameters passed in
to make sure they are legal and then call the equivalent kernel
routines already implemented in
(You
should not implement thread
Note that you will need to "bullet-proof" the Nachos kernel from
user program errors -- there should be nothing a user program can do
to crash the operating system (with the exception of explicitly asking
the system to halt). Therefore, your system call implementations
should do whatever error checking is necessary to ensure that they
will succeed or will cause the user's program to fail, but not nachos.
Your
If you add a .h file in the
Here are the changes made to the
In order to compile your user programs, make appropriate changes to
the
The Assignment
The items of the assignment are listed in the order in which you
should attempt them. Later ones are either more difficult or build
upon earlier ones.
syscall.h.
Your implementation goes in
ExceptionHandler in exception.cc. (See how
halt is defined in syscall.h and implemented
in exception.cc.)filesys/filesys.h and
filesys/openfile.h. Note that we are using the stub
implementation of the file system for this assignment.
Create
exception.cc
contains the function UserToKernelString which can be
used for this purpose.Open
exit can close them. You should allow up to 16 files to
be open at one time.
Remember to copy the filename from the user
specified string to a kernel string. Close
Read
exception.cc
contains a function, KernelToUser, which can be used for
this purpose. Write
exception.cc
contains a function, UserToKernel, which can be used for
this purpose. Length
Exit
StartProcess in progtest.cc in the userprog
directory to understand how nachos starts up and executes user
programs to help you understand what you need to do to exit one.
Remember to close all the files that the process opened. (Since we are not
implementing fork in this lab, it is safe for you to
assume that a user's program only contains one thread.)
machine.h.
For all exceptions except SyscallException, your exception
handlers should print an error message and exit the
user's program.SynchConsole class. This provides
synchronous access to the simulated hardware console. The hardware
console (implemented in the Console class defined in machine/console.cc)
provides non-blocking PutChar and
GetChar operations. These send a command to the
simulated I/O hardware and immediately return without waiting for the
I/O to complete. Your
SynchConsole class should
provide PutChar and
GetChar operations that only return after the I/O is
complete. The ConsoleTest procedure in
progtest.cc
has the beginnings of a SynchConsole implementation.
fork, yield,
exec, and join.)How to Turn in Lab 3
All of the following files and hard copies must be turned in
to get full credit for a question.
// Start changes
put your changes here
// End changes
You should put all your modified files in a lab3
subdirectory of your cs377 directory.nachos executable (from the
userprog directory should also be in the
cs377/lab3 directory.
~/cs377/lab3 directory
should also contain the README file.Tips
exception.cc.halt is compiled.gmake depend
before gmake nachos.gmake nachos to create a new
executable. userprog directory
with the -x option to run a
user program on top of Nachos. You need to do this to test your system
call implementations.code/Makefile.common. You will find several statements
defining variables used by gmake. Find the variables
related to the directory you put the new file in and the type of file
it is (.h or .cc). Add your filename to the appropriate list. If you
add a .cc file, you must modify both the c list and o list. For
example, Makefile.common includes:
USERPROG_H = ../userprog/addrspace.h\
../userprog/bitmap.h\
../userprog/SynchConsole.h\
../filesys/filesys.h\
../filesys/openfile.h\
../machine/console.h\
../machine/machine.h\
../machine/mipssim.h\
../machine/translate.h
USERPROG_C = ../userprog/addrspace.cc\
../userprog/bitmap.cc\
../userprog/exception.cc\
../userprog/progtest.cc\
../userprog/SynchConsole.cc\
../machine/console.cc\
../machine/machine.cc\
../machine/mipssim.cc\
../machine/translate.cc
USERPROG_O = addrspace.o bitmap.o exception.o progtest.o console.o machine.o \
mipssim.o translate.o SynchConsole.o
userprog directory, you must
add the name to the USERPROG_H list. If you add a .cc
file, you must add the corresponding names to the
USERPROG_C and USERPROG_O lists.
If your new .h file is included in one or more files in a different
directory, you should also put the .h file on the other directory's h
list. Be sure to
run gmake depend before gmake nachos.-d m shows reads and writes of registers and
each machine instruction being simulated. -d a shows all
reads and writes of memory. -d t shows scheduling
activity. -s allows you to single-step through the user's
program stopping after every simulated machine instruction.
Testing System Calls: Running User Programs
Here is a sample user program. You should make up your own test
programs to provide more complete testing.
/* Program to test I/O */
/* Reads, writes to stdin and stdout; opens a file and writes stuff to it. */
#include "syscall.h"
#define numloop 500
int
main()
{
int i;
char *ch = "A";
OpenFileId fd;
char buffer[24];
i= Read(buffer,2,ConsoleInput); /* read from console */
Write(buffer,2,ConsoleOutput); /* write the same thing to console */
fd = Open("pa.c.bak"); /* open a file */
i = Read(buffer,7,fd); /* Read from it */
Write(buffer,i,ConsoleOutput); // write chars just read from
// file on the screen
Close(fd);
/* Write a bunch of A's on the screen */
for (i=0;i<numloop;i++)
Write(ch,1,ConsoleOutput);
Exit(0);
}
Makefile in the test
directory in order to compile the user program printa.c:
all: halt shell matmult sort printa
printa.o: printa.c
$(CC) $(CFLAGS) -c printa.c
printa: printa.o start.o
$(LD) $(LDFLAGS) start.o printa.o -o printa.coff
../bin/coff2noff printa.coff printa
Makefile in the test directory and type make all
at the prompt while in the test directory.