Assignment 2: System calls and processes


  1. Due dates and mark distribution
  2. Introduction
  3. Code Walk-Through
  4. Basic Assignment
  5. Advanced Assignment

1. Due Dates and Mark Distribution

2. Introduction

3. Code walk-through

4. Basic Assignment

You have now completed setting up a shared repository for both partners. The following instructions are now for both partners.

Building and Testing Your Assignment

Configure OS/161 for Assignment 2

Before proceeding further, configure your new sources.

% cd ~/cs3231/asst2-src
% ./configure

Unlike previous the previous assignment, you will need to build and install the user-level programs that will be run by your kernel in this assignment.

% cd ~/cs3231/asst2-src
% make
Note: "make" in this directory does both "make" and "make install".

For your kernel development, again we have provided you with a framework for you to run your solutions for ASST2.

You have to reconfigure your kernel before you can use this framework. The procedure for configuring a kernel is the same as in ASST0 and ASST1, except you will use the ASST2 configuration file:

% cd ~/cs3231/asst2-src/kern/conf	
% ./config ASST2
You should now see an ASST2 directory in the compile directory.

Building for ASST2

When you built OS/161 for ASST1, you ran make from compile/ASST1 . In ASST2, you run make from (you guessed it) compile/ASST2.
% cd ../compile/ASST2
% make depend
% make
% make install
If you are told that the compile/ASST2 directory does not exist, make sure you ran config for ASST2.

Command Line Arguments to OS/161

Your solutions to ASST2 will be tested by running OS/161 with command line arguments that correspond to the menu options in the OS/161 boot menu.

IMPORTANT: Please DO NOT change these menu option strings!

Running "asst2"

For this assignment, we have supplied a user-level OS/161 program that you can use for testing. It is called asst2, and its sources live in src/testbin/asst2.

You can test your assignment by typing p /testbin/asst2 at the OS/161 menu prompt. As a short cut, you can also specify menu arguments on the command line, example: sys161 kernel "p /testbin/asst2".
Note: On cygwin, you need to type p /testbin/asst2.exe.
Note: If you don't have a sys161.conf file, you can use
this one.

Running the program produces output similar to the following prior to starting the assignment.

Unknown syscall 6
Unknown syscall 6
Unknown syscall 6
Unknown syscall 6
Unknown syscall 6
Unknown syscall 6
Unknown syscall 0
asst2 produces the following output on a (maybe partially) working assignment.
OS/161 kernel [? for menu]: p /testbin/asst2
Operation took 0.000212160 seconds
OS/161 kernel [? for menu]:
* File Tester
* write() works for stdout
* write() works for stderr
* opening new file "test.file"
* open() got fd 3
* writing test string
* wrote 45 bytes
* writing test string again
* wrote 45 bytes
* closing file
* opening old file "test.file"
* open() got fd 3
* reading entire file into buffer
* attemping read of 500 bytes
* read 90 bytes
* attemping read of 410 bytes
* read 0 bytes
* reading complete
* file content okay
* testing lseek
* reading 10 bytes of file into buffer
* attemping read of 10 bytes
* read 10 bytes
* reading complete
* file lseek  okay
* closing file
Unknown syscall 0

The Assignment: File System Calls

Implement the following file-based system calls. The full range of system calls that we think you might want over the course of the semester is listed in kern/include/kern/callno.h. For this assignment you should implement: open, read, write, lseek, close, dup2. Note: You are implementing the kernel code that implements the system call functionality within the kernel. The C stubs that user-level applications call to invoke the system calls are already automatically generated when you build OS/161.

Note that the basic assignment does not involve implementing fork (that's part of the advanced assignment). However, the design and implentation of your system calls should nonetheless not assume a single process.

It's crucial that your syscalls handle all error conditions gracefully (i.e., without crashing OS/161.) You should consult the OS/161 man pages included in the distribution and understand fully the system calls that you must implement. You must return the error codes as decribed in the man pages. Additionally, your syscalls must return the correct value (in case of success) or error code (in case of failure) as specified in the man pages. Some of the auto-marking scripts rely on the return of appropriate error codes; adherence to the guidelines is as important as the correctness of the implementation. The file include/unistd.h contains the user-level interface definition of the system calls that you will be writing for OS/161 (including ones you will implement in later assignments). This interface is different from that of the kernel functions that you will define to implement these calls. You need to design this interface and put it in kern/include/syscall.h. As you discovered (ideally) in Assignment 0, the integer codes for the calls are defined in kern/include/kern/callno.h. You need to think about a variety of issues associated with implementing system calls. Perhaps, the most obvious one is: can two different user-level processes (or user-level threads, if you choose to implement them) find themselves running a system call at the same time?

open(), read(), write(), lseek(), close(), and dup2()

For any given process, the first file descriptors (0, 1, and 2) are considered to be standard input (stdin), standard output (stdout), and standard error (stderr) respectively. For this basic assignment, the file descriptors 1 (stdout) and 2 (stderr) must start out attached to the console device ("con:"). You will probably modify runprogram() to achieve this. Your implementation must allow programs to use dup2() to change stdin, stdout, stderr to point elsewhere.

Although these system calls may seem to be tied to the filesystem, in fact, these system calls are really about manipulation of file descriptors, or process-specific filesystem state. A large part of this assignment is designing and implementing a system to track this state. Some of this information (such as the cwd) is specific only to the process, but others (such as offset) is specific to the process and file descriptor. Don't rush this design. Think carefully about the state you need to maintain, how to organise it, and when and how it has to change.

While this assignment requires you to implement file-system-related system calls, you actually have to write virtually no low-level file system code in this assignment. You will use the existing VFS layer to do most of the work. Your job is to construct the subsystem that implements the interface expected by user-level programs by invoking the appropriate VFS and vnode operations.

While you are not restricted to only modifying these files, please place most of your implementation in the following files: function prototypes and data types for your file subsystem in src/kern/include/file.h, and the function implementations and variable instantiations in src/kern/userprog/file.c.

A note on errors and error handling of system calls

The man pages in the OS/161 distribution contain a description of the error return values that you must return. If there are conditions that can happen that are not listed in the man page, return the most appropriate error code from kern/errno.h. If none seem particularly appropriate, consider adding a new one. If you're adding an error code for a condition for which Unix has a standard error code symbol, use the same symbol if possible. If not, feel free to make up your own, but note that error codes should always begin with E, should not be EOF, etc. Consult Unix man pages to learn about Unix error codes. Note that if you add an error code to src/kern/include/kern/errno.h, you need to add a corresponding error message to the file src/lib/libc/strerror.c.

Design Questions

Here are some additional questions and issues to aid you in developing your design. They are by no means comprehensive, but they are a reasonable place to start developing your solution.

What primitive operations exist to support the transfer of data to and from kernel space? Do you want to implement more on top of these?

You will need to "bullet-proof" the OS/161 kernel from user program errors. There should be nothing a user program can do to crash the operating system when invoking the file system calls. It is okay in the basic assignment for the kernel to panic for an unimplemented system call (e.g. execv()), or a user-level program error.

Decide which functions you need to change and which structures you may need to create to implement the system calls.

How you will keep track of open files? For which system calls is this useful?

For additional background, consult one or more of the following texts for details how similar existing operating systems structure their file system management:

Documenting your solution

This is a compulsory component of this assignment. You must submit a small design document identifying the basic issues in this assignment, and then describe your solution to the problems you have identified. The design document you developed in the planning phase (outlined above) would be an ideal start. The document must be plain ASCII text. We expect such a document to be roughly 500 - 1000 words, i.e. clear and to the point.

The document will be used to guide our markers in their evaluation of your solution to the assignment. In the case of a poor results in the functional testing combined with a poor design document, we will base our assessment on these components alone. If you can't describe your own solution clearly, you can't expect us to reverse engineer the code to a poor and complex solution to the assignment.

Create your design document to the top of the source tree to OS/161 (~/cs3231/asst2-src), and include it in svn as follows.

% cd ~/cs3231/asst2-src
% svn add design.txt

When you later commit your changes into your repository, your design doc will be included in the commit, and later in your submission.

Also, please word wrap you design doc if your have not already done so. You can use the unix fmt command to achieve this if your editor cannot.

Basic Assignment Submission

As with the previous assignments, you again will be submitting a diff of your changes to the original tree.

You should first commit your changes back to the repository using the following command. Note: You will have to supply a comment on your changes. You also need to coordinate with your partner that the changes you have (or potentially both have) made are committed consistently by you and your partner, such that the repository contains the work you want from both partners.

% cd ~/cs3231/asst2-src
% svn commit
If the above fails, you may need to run svn update to bring your source tree up to date with commits made by your partner. If you do this, you should double check and test your assignment prior to submission.

Beware! If you have created new files for this assignment, they will not be included in your submission unless you add them, using svn add:

% svn add filename.c
If you add files after running svn commit, you will need to run svn commit again.

Now generate a file containing the diff.

% cd ~
% svn diff file:///home/osprjXXX/repo/asst2/initial
file:///home/osprjXXX/repo/asst2/trunk >~/asst2.diff

Testing Your Submission

here for information on testing and resubmitting your assignment.

Submitting Your Assignment

Now submit the diff as your assignment.
% cd ~
% give cs3231 asst2 asst2.diff
You're now done.

Even though the generated diff output should represent all the changes you have made to the supplied code, occasionally students do something "ingenious" and generate non representative diff output.

We strongly suggest keeping your svn repository intact to allow for recovery of your work if need be.

5. Advanced Assignment

The advanced assignment is to complete the basic assignment, plus one of either 5.1 or 5.2 below. Remember that you must finish the basic assignment, then get approval from the lecturer in charge, Kevin Elphinstone, at least one week before the due date. Whether you attempt the first or second advanced assignment, you should submit using the instructions at the bottom. [If you attempt both parts, submit a diff containing the code for both - they should not conflict.]

Given you're doing the advanced version of the assignment, I'm assuming you're competent with managing your SVN repository and don't need simple directions. You basically need to geneerate a diff between your final version and the base. There are two ways you can do this: the simpler (but messier) option is to continue developing along your mainline branch and generate the diff in the same way as for asst2. A neater approach is to create a new branch in SVN to work on your advanced solution. Whichever approach you take, make sure you test your diff before you submit it!

5.1 New System Call

5.2 User-level Process Management System Calls

Advanced Assignment Submission

Submission for the advanced assignment is similar to the basic assignment, except the advance component is given to a distinguished assignment name: asst2_adv Again, you need to generate a diff based on the original source tree.
% cd ~/cs3231/asst2-src
% svn commit

Now generate a file containing the diff. (NOTE: How this works depends on whether you have set up branches in SVN. See above.)

% cd ~
% svn diff file:///home/osprjXXX/repo/asst2/initial
file:///home/osprjXXX/repo/asst2/trunk >~/asst2_adv.diff
Submit your solution
% cd ~
% give cs3231 asst2_adv asst2_adv.diff