Handed out Friday, April 16, 2010
Project proposals due April 23, 2010, 3:00 PM
Code due Sunday, May 9, 2010, 9:00 PM
Project demos: either during last day of class, during finals week, or
not at all (see below)
Deadline for making a decision about the demo: Monday, May 3, 2010, 9:00 PM
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 are strongly encouraged to work in pairs. Those of you who have been pair programming must keep coding together. Those who have not are strongly encouraged to find a partner.
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) by April 23. 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 a paragraph, please).
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:
mig% cd ~/CS372H/lab mig% git commit -am 'my solution to lab6' Created commit 734fab7: my solution to lab6 4 files changed, 42 insertions(+), 9 deletions(-) mig% git pull Already up-to-date. mig% git checkout -b lab7 origin/lab7 Branch lab7 set up to track remote branch refs/remotes/origin/lab7. Switched to a new branch "lab7" mig% git merge lab6 Merge made by recursive. fs/fs.c | 42 +++++++++++++++++++ 1 files changed, 42 insertions(+), 0 deletions(-) mig%Demos
You have three choices about when to demo. First, you can do a five-minute demo during our last class meeting. Second, you can schedule a time with the course staff between May 12 and May 17 (exact slots and sign-up to be posted). Third, you can skip the demo. This last option may have a certain appeal, but please note that there is a disadvantage, which is that you'll need to tell us exactly how to run your code, and it may not run for us the way that it does for you.
If you want to do a demo in class, great! Your deadline for deciding is Monday May 3, 9:00 PM.
Late policy and procedure for submitting the assignment.Late policy: Pair teams will have the same number of late hours that they have had all along. For newly paired teams, you must hand in the individual portion as if you had the minimum of the two team members' late hours, and you can hand in the project portion as if you had the maximum of the two team members' late hours. Two notes here: (1) We recognize that this is not perfectly fair (in the sense of treating everyone exactly the same), but we couldn't think of a perfectly equitable approach that is also simple to implement. As with computer systems, we are trying to get this roughly right at minimal implementation cost. (2) If, as a member of a newly paired team, you feel that this policy puts you at a disadvantage (say because you had many late hours stored up that you wanted to use for the individual portion of lab 7), please let us know.
Turn in procedure: You will submit this lab in two parts. Once you have completed exercises 1, 2, and 3, do 'make turnin' to submit your solutions to this part of the lab. To submit your final project code, do 'make project-turnin'. Note that you need not do these in order. It's more important to get your project working than to pass the grading scripts for exercises 1, 2, and 3. (Note that you still need to do those exercises on your own if you are on the individual track.) On the other hand, you may find it useful in your final project to have a working shell, so there may be good technical reasons to do the lab in order.
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 that running "(date; ls) >file
" will
not work properly, because even though date
updates its own file offset,
ls
will not see the change.)
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.)
Use make run-testpteshare 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 table pages and the file data pages get mapped
with PTE_SHARE
.
Use make run-testfdsharing
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 data page
succeeded".
Note: the prior two exercises, and the one below, may tickle bugs in lab 5. We've included some hints about correct operation of lab 5 code. You may wish to check these hints, and you may need to revisit your lab 5 code.
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. (The same was true of Bochs.) 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 xrun-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. You may notice that output from other
environments starting up appears when you first begin typing.
This is because sys_cgetc
, unlike any other JOS
system call, blocks in the kernel, which prevents other
environments from running when one environment is waiting on
input.
Run make xrun-icode
. This will run your kernel inside the
X11 Bochs starting user/icode
. But what the heck is
icode
? Take a look at user/icode.c
. This
program 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:
ls echo hello world | cat cat lorem >out cat out cat lorem |num cat lorem |num |num |num |num |num lsfd cat script sh <script
You can also play around with the (primitive) shell, though you will see that there are some obvious limitations, like that the shell cannot create new files with its redirect operator.
Note that the user library routines cprintf
and
printf
print 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, "...", ...)
. See user/ls.c
for examples.
Run make run-testshell 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.
At this point, you should probably commit your code to your local git repo and use make turnin to submit it.
Challenge! Do an awesome final project!
make grade
and hand it in with 1. make
turnin
for the initial exercises and 2. make project-turnin
after completing the project.
Congratulations on having completed all of the CS 372H labs! We are looking forward to seeing your projects!