This lab makes you familiar with xv6 and its system calls.
Install qemu and gcc for RISC-V following the directions on the tools page.
Fetch the xv6 source for the lab and check out a new branch for your solution to this lab:
The xv6-19au repository differs slightly from the book’s xv6-riscv in order to make the labs easier.
The files you will need for this and subsequent lab assignments in this course are distributed using the Git version control system. Above you created a new branch (“util”) for your solutions for the utilities 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:
You can keep track of your changes by using the git diff command.
For example,
running git diff will display the changes to your code since your last commit,
and git diff origin/xv6-19au will display the changes relative to the initial
xv6-19au code. Here, origin/xv6-19au
is the name of the git branch with the initial code you downloaded for the class.
Build xv6:
If you type ls at the prompt, you should see output similar to the following:
These are the programs/files that mkfs
includes in the initial
file system. You just ran one of them: ls
.
To quit QEMU, type Ctrl-a x.
You may create a private fork of the xv6 repository for collaboration or backup (e.g., using the CSE GitLab). You can add this new repository as a git remote to which you can push/pull your commits. For example, to back up branch to a remote named “mybackup” for the repository at url, you can run:
Do not host your lab code on publicly accessible web sites (e.g., GitHub) or file spaces (e.g., CSE GitLab’s non-private projects).
To turn in your assignments, use make tarball to make a tar file, and upload the file via Canvas.
If you have either uncomitted changes or untracked files, you will see output similar to the following:
Inspect the above lines and make sure all files that your lab
solution needs are tracked (i.e., not listed in a line that begins
with ??
). You can cause git to track a new file that you create using
git add filename.
You can run make grade to test your solutions with the grading program. We 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:
user/
to see how you can obtain the command-line arguments passed to a program. If the user forgets to pass an argument, sleep should print an error message.atoi
(see user/ulib.c
).sleep
(see user/usys.S
and kernel/sysproc.c
).exit()
in order to exit your program.UPROGS
in Makefile
and compile user programs by typing make fs.img.Run the program from the xv6 shell:
Your solution is correct, if your program behaves as shown above.
Optional: write an uptime program that prints the uptime in terms of ticks using the uptime
system call.
Write a program that uses Unix system calls to “ping-pong” a byte
between two processes over a pair of pipes, one for each direction.
The parent sends by writing a byte to parent_fd[1]
and the child
receives it by reading from parent_fd[0]
. After receiving a byte
from parent, the child responds with its own byte by writing to
child_fd[1]
, which the parent then reads. Your solution should be
in the file user/pingpong.c
.
Some hints:
pipe
to create a pipe.fork
to create a child.read
to read from the pipe, and write
to write to the pipe.Run the program from the xv6 shell and it should produce the following output:
Your solution is correct, if your program behaves as shown above.
The number before “:” is the process id of the process printing the
output. You can get the process id by calling the system call getpid
.
Write a concurrent version of prime sieve using pipes. This idea
is due to Doug McIlroy, inventor of Unix pipes. The picture halfway
down this page and the surrounding
text explain how to do it. Your solution should be in the file
user/primes.c
.
Your goal is to use pipe
and fork
to set up the pipeline. The
first process feeds the numbers 2 through 35 into the pipeline. For
each prime number, you will arrange to create one process that reads
from its left neighbor over a pipe and writes to its right neighbor
over another pipe. Since xv6 has limited number of file descriptors
and processes, the first process can stop at 35.
Some hints:
int
s to the pipes, rather than using formatted ASCII I/O.Your solution is correct if it produces the following output:
Write a simple version of the Unix find program: find all the files
in a directory tree whose name matches a string. Your solution
should be in the file user/find.c
.
Support regular expressions in name matching. grep.c
has some primitive support for regular expressions.
Some hints:
user/ls.c
to see how to read directories.Your solution is correct if produces the following output (when the file system contains a file a/b
):
Changes to the file system persist across runs of QEMU.
To get a clean file system, run make clean and then make qemu.
Write a simple version of the Unix xargs program: read lines from
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
.
The following example illustrates xarg’s behavior:
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”.
Some hints:
fork
and exec
system call to invoke the command on each
line of input. Use wait
in the parent to wait for the child to
complete running the command.kernel/param.h
declares MAXARG
, which may be useful if you need to declare an argv.xargs, find, and grep combine well:
will run “grep hello” on each file named b
in the directories below “.
”.
To test your solution for xargs, run the shell script xargstest.sh
.
Your solution is correct if it produces the following output:
You may have to fix bugs in your find program. The output has many
$
because the xv6 shell is primitive and doesn’t realize it is
processing commands from a file instead of from the console, and
prints a $
for each command in the file.
There are endless ways in which the shell could be extended. Here are some suggestions:
$
when processing shell commands from a file.This completes the lab. In the lab directory, commit your changes, type make tarball, and submit the tarball through Canvas.