CS372H Spring 2011 Lab 7: Final Project (Mainly)

Handed out Friday, April 8, 2011
Project proposals due by email Friday, April 22, 2011, 3:00 PM
Part A due Friday, April 29, 2011, 9:00 PM
Part B due Monday, May 16, 2011, 9:00 PM
Project demos: May 4, 13, and 17, 2011
Deadline for project demo signup: May 1, 2011


In this lab you will flesh out your kernel and library operating system enough to run a shell on the console. This piece of the lab you will code as you have been all semester: alone or in pairs. You will then do the core of the lab: the final project. In this piece of the lab, you will work in pairs. Those of you who have been pair programming must keep coding together. Those who have not must find a partner.

Lab Requirements

Here is a list of examples and projects from past years and other versions of this course. This is meant to be inspiration only, not a menu. The actual project is up to you. Please pick something manageable. It is far better to complete your project to spec than it is to take on something too big and not have anything to show for it except excellent intentions (also true in the real world).

The project you choose must have a significant operating systems component. For example, you shouldn't simply port a user-level application that requires little or no kernel modification. You should email a proposal to the course staff email alias (not the course staff separately) at the deadline given above. The proposal must include: (1) The names of your group members; (2) What you want to do; and (3) What you are expecting to present (a list of deliverables). Please keep it short (no more than several paragraphs).

Getting Started

Use Git to commit your Lab 6 source, fetch the latest version of the course repository, and then create a local branch called lab7 based on our lab7 branch, origin/lab7:

tig% cd ~/CS372H/lab
tig% git commit -am 'my solution to lab6'
Created commit 734fab7: my solution to lab6
 4 files changed, 42 insertions(+), 9 deletions(-)
tig% git pull
Already up-to-date.
tig% git checkout -b lab7 origin/lab7
Branch lab7 set up to track remote branch refs/remotes/origin/lab7.
Switched to a new branch "lab7"
tig% git merge lab6
Merge made by recursive.
 fs/fs.c |   42 +++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)


You will need to give a 15 minute demonstration of your finished project to the course staff. Links to a signup sheet with available time slots will be emailed to the class. Both partners must be at the demo. The demo will be interactive: the course staff may ask questions, poke at your system, skim your code, etc.

[Update 4/25] The link to the signup sheet has been sent out. Please contact the course staff if you did not get an email.

Late policy and procedure for submitting the assignment.

Late policy: Part A of the lab will be treated as every other lab has been: you are welcome to use late hours, if you have them, and if you turn in part A late, your grade on that part of the lab decreases each day (as usual). However, you cannot use late hours for part B. If your part B is late, you will lose points according to the late policy but not beyond the end of the semester, i.e., if the semester ends with no project from you, we count the project as not handed in. This in turn will unfortunately trigger the non-linearity in the lab grading in which a not-turned-in lab causes an F on the entire lab portion of the grade (see the policies page).

Turn in procedure: You will submit this lab in two parts. Once you have completed part A, do make turnin-partA to submit your solutions to this part of the lab. To submit your final project code, do make turnin-partB.

Part A: Sharing Memory and a Shell

In the first part of this lab, you will change fork and spawn to automatically share certain pages when they create a new environment. You will also add some functionality to the kernel that will allow user environments to receive keyboard input, culminating in a primitive shell.

Sharing library code across fork and spawn

We would like to share file descriptor state across fork and spawn, but file descriptor state is kept in user-space memory. Right now, on fork, the memory will be marked copy-on-write, so the state will be duplicated rather than shared. (This means environments won't be able to seek in files they didn't open themselves and that pipes won't work across a fork.) On spawn, the memory will be left behind, not copied at all. (Effectively, the spawned environment starts with no open file descriptors.)

We will change fork to know that certain regions of memory are used by the "library operating system" and should always be shared. Rather than hard-code a list of regions somewhere, we will set an otherwise-unused bit in the page table entries (just like we did with the PTE_COW bit in fork).

We have defined a new PTE_SHARE bit in inc/lib.h. This bit is one of the three PTE bits that are marked "available for software use" in the Intel and AMD manuals. We will establish the convention that if a page table entry has this bit set, the PTE should be copied directly from parent to child in both fork and spawn. Note that this is different from marking it copy-on-write: as described in the first paragraph, we want to make sure to share updates to the page.

Exercise 1. Change duppage in lib/fork.c to follow the new convention. If the page table entry has the PTE_SHARE bit set, just copy the mapping directly. (Note that you should use PTE_USER, not PTE_FLAGS, to mask out the relevant bits from the page table entry. PTE_FLAGS picks up the accessed and dirty bits as well.)

Likewise, implement copy_shared_pages in lib/spawn.c. It should loop through all page table entries in the current process (just like fork did), copying any page mappings that have the PTE_SHARE bit set into the child process.

Use make run-testpteshare-nox to check that your code is behaving properly. You should see lines that say "fork handles PTE_SHARE right" and "spawn handles PTE_SHARE right".

Exercise 2. Change the file server so that all the file descriptor pages get mapped with PTE_SHARE.

Use make run-testfdsharing-nox to check that file descriptors are shared properly. You should see lines that say "read in child succeeded", "read in parent succeeded", and "write to file succeeded".

The keyboard interface

For the shell to work, we need a way to type at it. QEMU has been displaying output we write to the CGA display and the serial port, but so far we've only taken input while in the kernel monitor. In QEMU, input typed in the graphical window appears as input from the keyboard to JOS, while input typed to the console appears as characters on the serial port. kern/console.c already contains the keyboard and serial drivers that have been used by the kernel monitor since lab 1, but now you need to attach these to the rest of the system.

Exercise 3. In your kern/trap.c, call kbd_intr to handle trap IRQ_OFFSET+IRQ_KBD and serial_intr to handle trap IRQ_OFFSET+IRQ_SERIAL.

We implemented the console input/output file type for you, in lib/console.c.

Test your code by running make run-testkbd and type a few lines. The system should echo your lines back to you as you finish them. Try typing in both the console and the graphical window, if you have both available.

The Shell

Run make run-icode or make run-icode-nox. This will run your kernel and start user/icode. icode execs init, which will set up the console as file descriptors 0 and 1 (standard input and standard output). It will then spawn sh, the shell. You should be able to run the following commands:

	echo hello world | cat
	cat lorem >out
	cat out
	cat lorem |num
	cat lorem |num |num |num |num |num
	cat script
	sh <script

Note that the user library routine cprintf prints straight to the console, without using the file descriptor code. This is great for debugging but not great for piping into other programs. To print output to a particular file descriptor (for example, 1, standard output), use fprintf(1, "...", ...). printf("...", ...) is a short-cut for printing to FD 1. See user/lsfd.c for examples.

Run make run-testshell-nox to test your shell. testshell simply feeds the above commands (also found in fs/testshell.sh) into the shell and then checks that the output matches fs/testshell.key.

Your code should pass all tests at this point. This completes part A of the lab. As usual, you can grade your submission with make grade and turn it in with make turnin-partA.

Part B: The Project

In the second part of this lab, you will do a final project that you choose and that the course staff approves. Details about the project, the proposal process, and what is expected are specified at the beginning of the lab.

Once you complete your project, you must turn in a tarball of your code as usual, including a brief write-up of what you did and how, using make turnin-partB. In addition, you will demonstrate your final project for the course staff in person. See the Demos section for details.

Challenge! Do an awesome final project!

Congratulations on having completed all of the CS372H labs! We are looking forward to seeing your projects!