Salsa - User Programs Topics Nachos Multiprogramming in Nachos

The routine ExceptionHandler() is the entry point into the kernel for a trap caused by a user program. This means that the code for all the system calls you implement should go in that routine.


[ Source code in code/userprog | Lab| Quiz ]

In order to understand how user programs execute in Nachos, it is crucial to understand the underlying machine architecture that Nachos provides and how user programs access it. A detailed explanation is provided here.

How to compile and run user programs in Nachos

All user-level processes execute as a kernel-level thread in Nachos.

Nachos can run arbitrary user programs as long as they make only those system calls that are understood by Nachos. One difference between the programs executed on UNIX and those executed by Nachos is that UNIX executables are in the coff format whereas the Nachos executables are in the Noff format. Thus, in order to run user programs on Nachos, we first compile them using gcc and then convert them from the coff format to the Noff format. This is done using the coff2noff program which is present in the bin directory.

In order to see how this is done, here are a few statements from the Makefile in the test directory:


halt.o: halt.c
        $(CC) $(CFLAGS) -c halt.c
halt: halt.o start.o
        $(LD) $(LDFLAGS) start.o halt.o -o halt.coff
        ../bin/coff2noff halt.coff halt

The above compiles a user program called halt.c . The resulting object file is then linked with another file called start.o to produce a binary called halt.coff . Remember that this will be in the coff format that UNIX uses. Since we want to run halt.c in Nachos, we then invoke the program coff2noff to produce a binary file called halt in the Noff format.

The data structures for the Noff format are defined in noff.h in the bin directory.

Noff format files consist of four parts.

For each of the last three sections of the file, the Noff header contains information in the following variables:

Makefile Revisited

The test directory contains some sample user programs that Nachos can run and also a Makefile that compiles them for Nachos.


1  all: halt shell matmult sort

2  start.o: start.s ../userprog/syscall.h
3        $(CPP) $(CPPFLAGS) start.s > strt.s
4        $(AS) $(ASFLAGS) -o start.o strt.s
5        rm strt.s

6  shell.o: shell.c
7        $(CC) $(CFLAGS) -c shell.c
8  shell: shell.o start.o
9        $(LD) $(LDFLAGS) start.o shell.o -o shell.coff
10       ../bin/coff2noff shell.coff shell

The above statements from the Makefile show how to compile shell.c for Nachos. The file start.s contains assembly language code that needs to be executed before the code of each user program's main routine. Thus, for proper execution of shell.c , we need to make sure that the code in start.s resides before that of its main program. (In addition to containing this initialization code, start.s also contains stub modules for invoking system calls .)

Lines 2-5 generate object code for start.s . Lines 6 and 7 generate object code for shell.c . Lines 8 and 9 produce an executable binary. Note that listing start.o before shell.o ensures that the code for start.s resides before that of the main program. Finally, line 10 translates the binary into the Noff format. shell, is thus, an executable ready to execute under Nachos.

Commands to compile and run the user programs

Typing make all in the test directory will compile the user programs called halt.c, shell.c, matmult.c and sort.c . This command works because of line 1 in the Makefile above. Thus, any user programs you write can be compiled in the same way shell.c is being compiled above. Simply add analogous statements to the Makefile for your test program. Also remember to add the name of your executable test program to line 1.

To run the test programs in Nachos, use the -x option. For example, to run the test program shell, type nachos -x ../test/shell while in the userprog directory.

A list of options available for running Nachos is in main.cc.

How system calls and exception handling work in Nachos

User programs invoke system calls by executing the MIPS syscall instruction, which generates a trap into the Nachos kernel. The MIPS simulator implements traps by invoking the routine RaiseException() (see machine.cc), passing it appropriate arguments indicating the exact cause of the trap. RaiseException() , in turn, calls the routine ExceptionHandler() (see exception.cc) to take care of the problem. ExceptionHandler() is passed an argument indicating the kind of exception that has been raised.

A list of exceptions that can be raised within Nachos is in machine.h. The list of system calls in Nachos is in syscall.h.

FIGURE trap.gif WILL BE HERE.

The actual instructions for making system calls are found in start.s . At runtime, a code indicating the type of system call is placed in register 2 and the syscall instruction is executed. Additional arguments to the system call are placed in registers 4-7, following standard C procedure call linkage conventions. Any return values are expected to be in register 2. The syscall instruction is a trap instruction, meaning the next instruction to be executed is the first instruction is the trap handler. In Nachos, the trap handler is the routine ExceptionHandler() . The following code from start.s shows the how the Halt and Exit system calls are invoked:


1   #include "syscall.h"
2      .text
3      .align 2
4
5      .globl __start
6      .ent   __start
7   __start:
8      jal    main      /* Call the procedure "main" */
9      move   $4,$0     /* R4 gets 0 */
10     jal    Exit      /* If we return from main, exit(0) */
11     .end   __start
12
13     .globl Halt
14     .ent   Halt
15  Halt:
16     addiu  $2,$0,SC_Halt
17     syscall
18     j      $31
19     .end   Halt
20
21     .globl Exit
22     .ent   Exit
23  Exit:
24     addiu  $2,$0,SC_Exit
25     syscall
26     j      $31
27     .end   Exit
28  /* dummy function to keep gcc happy */
29     .globl __main
30     .ent   __main
31  __main:
32     j      $31
33     .end   __main

Line 8 is the first actual instruction, lines 1-7 being assembler directives. It simply calls the procedure main , in the user program. Lines 9 and 10 are executed whenever the call to main returns, in which case we tell Nachos we are done via the exit system call. Lines 15-18 invoke the Halt system call. Similarly, lines 23-26 invoke the Exit system call. Note the call to the syscall instruction on lines 17 and 25. Also note that the Exit system call normally will not return but a return is provided here anyway.

The routine RaiseException() is called within the simulator - mipssim.cc and translate.cc .

Source code in code/userprog
Lab
Quiz

Back to Top

Last modified on Monday, 29-Mar-99 00:29:55 EST