This lab will familiarize you with xv6 and its system calls.
You can do these labs on Sledge or on your own computer. If you use your own computer, have a look at the lab tools page for setup tips.
Fetch the xv6 source for the lab and check out the util branch:
$ git clone git@github.com:hengyin/xv6-riscv.git
Cloning into 'xv6-riscv'...
...
$ cd xv6-riscv
$ git checkout util
Branch 'util' set up to track remote branch 'util' from 'origin'.
Switched to a new branch 'util'
This repository differs slightly from the book's xv6-riscv; it mostly adds some files. If you are curious look at the git log:
$ git log
The files you will need for this and subsequent lab assignments are distributed using the Git version control system. Above you switched to a branch (git checkout util) containing a version of xv6 tailored to this lab. To learn more about Git, take a look at the Git user's manual, or, you may find this CS-oriented overview of Git useful. Git allows you to keep track of the changes you make to the code. For example, if you are finished with one of the exercises, and want to checkpoint your progress, you can commit your changes by running:
$ git commit -am 'my solution for util lab exercise 1'
Created commit 60d2135: my solution for util lab exercise 1
1 files changed, 1 insertions(+), 0 deletions(-)
$
You can keep track of your changes by using the git diff command. Running git diff will display the changes to your code since your last commit, and git diff origin/util will display the changes relative to the initial xv6-riscv code. Here, origin/util is the name of the git branch with the initial code you downloaded for the class.
Build and run xv6:
$ make qemu
riscv64-unknown-elf-gcc -c -o kernel/entry.o kernel/entry.S
riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -DSOL_UTIL -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -c -o kernel/start.o kernel/start.c
...
riscv64-unknown-elf-ld -z max-page-size=4096 -N -e main -Ttext 0 -o user/_zombie user/zombie.o user/ulib.o user/usys.o user/printf.o user/umalloc.o
riscv64-unknown-elf-objdump -S user/_zombie > user/zombie.asm
riscv64-unknown-elf-objdump -t user/_zombie | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > user/zombie.sym
mkfs/mkfs fs.img README user/xargstest.sh user/_cat user/_echo user/_forktest user/_grep user/_init user/_kill user/_ln user/_ls user/_mkdir user/_rm user/_sh user/_stressfs user/_usertests user/_grind user/_wc user/_zombie
nmeta 46 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 1) blocks 954 total 1000
balloc: first 591 blocks have been allocated
balloc: write bitmap block at sector 45
qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
xv6 kernel is booting
hart 2 starting
hart 1 starting
init: starting sh
$
If you type ls at the prompt, you should see output similar to the following:
$ ls
. 1 1 1024
.. 1 1 1024
README 2 2 2059
xargstest.sh 2 3 93
cat 2 4 24256
echo 2 5 23080
forktest 2 6 13272
grep 2 7 27560
init 2 8 23816
kill 2 9 23024
ln 2 10 22880
ls 2 11 26448
mkdir 2 12 23176
rm 2 13 23160
sh 2 14 41976
stressfs 2 15 24016
usertests 2 16 148456
grind 2 17 38144
wc 2 18 25344
zombie 2 19 22408
console 3 20 0
These are the files that mkfs includes in the
initial file system; most are programs you can run. You just ran one of them: ls.
xv6 has no ps command, but, if you type Ctrl-p, the kernel will print information about each process. If you try it now, you'll see two lines: one for init, and one for sh.
To quit qemu type: Ctrl-a x.
You can run make grade
to test your solutions with the grading program. The TAs will use the same
grading program to assign your lab submission a
grade.
Implement the UNIX program sleep for xv6; your sleep should pause
for a user-specified number of ticks. A tick is a notion of time
defined by the xv6 kernel, namely the time between two interrupts
from the timer chip. Your solution should be in the file
user/sleep.c.
Some hints:
Run the program from the xv6 shell:
Your solution is correct if your program pauses when
run as shown above.
Run make grade to see if you indeed pass the
sleep tests.
Note that make grade runs all tests, including the ones for the assignments
below. If you want to run the grade tests for one assignment, type:
Write a simple version of the UNIX find program: find all the files
in a directory tree with a specific name. Your solution
should be in the file user/find.c.
Some hints:
Your solution is correct if produces the following output (when the
file system contains the files b and a/b):
Write a simple version of the UNIX xargs program: read lines from
the standard input and run a command for each line, supplying the line as
arguments to the command. Your solution
should be in the file user/xargs.c.
Please note that xargs on UNIX makes an optimization where it will feed more than argument to the command at a time. We don't expect you to make this optimization. To make xargs on UNIX behave the way we want it to for this lab, please run it with the -n option set to 1. For instance Some hints:
xargs, find, and grep combine well:
To test your solution for xargs, run the shell script xargstest.sh.
Your solution is correct if it produces the following output:
Grading
sleep
$ make qemu
...
init: starting sh
$ sleep 10
(nothing happens for a little while)
$
$ ./grade-lab-util sleep
This will run the grade tests that match "sleep". Or, you can type:
$ make GRADEFLAGS=sleep grade
which does the same.
find
$ make qemu
...
init: starting sh
$ echo > b
$ mkdir a
$ echo > a/b
$ find . b
./b
./a/b
$
xargs
$ echo hello too | xargs echo bye
bye hello too
$
Note that the command here is "echo bye" and the additional
arguments are "hello too", making the command "echo bye hello too",
which outputs "bye hello too".
$ echo "1\n2" | xargs -n 1 echo line
line 1
line 2
$
$ find . b | xargs grep hello
will run "grep hello" on each file named b in the directories below
".".
$ make qemu
...
init: starting sh
$ sh < xargstest.sh
$ $ $ $ $ $ hello
hello
hello
$ $
You may have to go back and fix bugs in your find program. The output has
many $ because the xv6 shell doesn't realize
it is processing commands from a file instead of from the console, and
prints a $ for each command in the file.