CSCE 451/851 Operating Systems Principles
Fall 1999
Steve Goddard
Homework 1 Solution & Notes for Problems 9, 10
Begin by downloading your own copy of the
Several documents have been created to introduce you to the Nachos system.
In this problem you will trace the execution of the Fork system call (many of the system calls in Nachos have the same name as their Unix counterpart with the first letter capitalized). The purpose of this exercise is to understand the control-flow in a Nachos system call. A subsidiary goal is to understand the finer points of an implementation of the Fork call.
There are two ways to trace the control flow in Nachos. First, you could read through the source code and note the major function calls, etc. The Nachos source is neat and well commented. As such, this is not a bad way to begin.
The second way is to use a debugger to step through the execution of the operating system. For the purposes of this assignment, we have provided a pre-compiled version of the user program below. You can use the SmartGDB debugger to step through Nachos while running it. This way involves more initial work in learning the debugger, but may assist in getting a general idea of what's going on faster than diving right into the code.
Given the following Nachos user program:
- int main( ) {
- int foo;
- Fork();
- foo = 1;
- }
Trace the execution of the program through the Nachos system from when it begins to execute the Fork call to the return of the main procedure.
Include the answers to the following questions with your trace:
We have done this using SmartGDB and a
TCL script that you can download and try yourself (if you have problems downloading the TCL script, click on the link with your right mouse button and choose "Save Link As" from the menu that pops up). Due to the size of the output, it is available on a separate page.The more complex answer involves understanding why the two process' memory spaces are identical. The AddrSpace::CopyFrom function allocates a new page table consisting of a TranslationEntry for each virtual page of memory the parent process has. It then sets up each TranslationEntry so that it points to the same physical page that the parent is using. Finally, it sets the Copy-On-Write (COW) flag in its TranslationEntry and the parent's. The Copy-On-Write flag indicates that whenever a process tries to write to the page that it must first make a new physical copy of the page (in a new frame in physical memory), reset its TranslationEntry to point to the new page and then clear the COW flag for its page table entry and the parent's.
For this question you only have to list calls and returns to major routines defined in thread.cc, scheduler.cc, switch.s, exception.cc, mipssim.cc, machine.cc, and systemcall.cc along with calls to Interrupt::SetLevel( ). In other words, you can ignore ASSERTs, DEBUG statements, calls to list routines, calls made internal to the interrupt simulation, any trivial inline functions, etc.
For example, your solution might begin:
You should assume for the purposes of this excercise that the following are true:
It is acceptable (even encouraged) to generate your solution automatically (either by code modifications or by SmartGDB scripts).
- int main( ) {
- Fork( );
- Yield( );
- }
We have done this using SmartGDB and a
TCL script that you can download and try yourself (if you have problems downloading the TCL script, click on the link with your right mouse button and choose "Save Link As" from the menu that pops up). Due to the size of the output, it is available on a separate page.