2019-07-24 18:20:27 +00:00
|
|
|
<html>
|
|
|
|
<head>
|
2019-07-25 00:30:20 +00:00
|
|
|
<title>Lab: xv6</title>
|
2019-07-24 18:20:27 +00:00
|
|
|
<link rel="stylesheet" href="homework.css" type="text/css" />
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
|
|
|
|
<h1>Lab: xv6</h1>
|
|
|
|
|
|
|
|
This lab makes you familiar with xv6 and its system calls.
|
|
|
|
|
|
|
|
<h2>Boot xv6</h2>
|
|
|
|
|
|
|
|
<p>Login to Athena (e.g., ssh -X athena.dialup.mit.edu) and attach the course
|
|
|
|
locker: (You must run this command every time you log in; or add it to your
|
|
|
|
~/.environment file.)
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
$ add -f 6.828
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>Fetch the xv6 source:
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
$ mkdir 6.828
|
|
|
|
$ cd 6.828
|
|
|
|
$ git clone git://github.com/mit-pdos/xv6-riscv.git
|
|
|
|
Cloning into 'xv6-riscv'...
|
|
|
|
...
|
|
|
|
$
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>XXX pointer to an update tools page
|
|
|
|
|
|
|
|
<p>Build xv6 on Athena:
|
|
|
|
<pre>
|
|
|
|
$ cd xv6-public
|
|
|
|
$ makeriscv64-linux-gnu-gcc -c -o kernel/entry.o kernel/entry.S
|
|
|
|
riscv64-linux-gnu-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -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
|
|
|
|
...
|
|
|
|
$ make qemu
|
|
|
|
...
|
|
|
|
mkfs/mkfs fs.img README 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/_wc user/_zombie user/_cow
|
|
|
|
nmeta 46 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 1) blocks 954 total 1000
|
|
|
|
balloc: first 497 blocks have been allocated
|
|
|
|
balloc: write bitmap block at sector 45
|
|
|
|
qemu-system-riscv64 -machine virt -kernel kernel/kernel -m 3G -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
|
|
|
hart 0 starting
|
|
|
|
hart 2 starting
|
|
|
|
hart 1 starting
|
|
|
|
init: starting sh
|
|
|
|
$
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>
|
|
|
|
If you type <tt>ls</tt> at the prompt, you should output similar to the following:
|
|
|
|
<pre>
|
|
|
|
$ ls
|
|
|
|
. 1 1 1024
|
|
|
|
.. 1 1 1024
|
|
|
|
README 2 2 2181
|
|
|
|
cat 2 3 21024
|
|
|
|
echo 2 4 19776
|
|
|
|
forktest 2 5 11456
|
|
|
|
grep 2 6 24512
|
|
|
|
init 2 7 20656
|
|
|
|
kill 2 8 19856
|
|
|
|
ln 2 9 19832
|
|
|
|
ls 2 10 23280
|
|
|
|
mkdir 2 11 19952
|
|
|
|
rm 2 12 19936
|
|
|
|
sh 2 13 38632
|
|
|
|
stressfs 2 14 20912
|
|
|
|
usertests 2 15 106264
|
|
|
|
wc 2 16 22160
|
|
|
|
zombie 2 17 19376
|
|
|
|
cow 2 18 27152
|
|
|
|
console 3 19 0
|
|
|
|
</pre>
|
|
|
|
These are the programs/files that <tt>mkfs</tt> includes in the
|
|
|
|
initial file system. You just ran one of them: <tt>ls</tt>.
|
|
|
|
|
|
|
|
<h2>sleep</h2>
|
|
|
|
|
2019-07-24 18:26:05 +00:00
|
|
|
<p>Implement the UNIX program sleep, which sleeps for a user-specified
|
|
|
|
number of ticks.
|
2019-07-24 18:20:27 +00:00
|
|
|
|
|
|
|
<p>Some hints:
|
|
|
|
<ul>
|
|
|
|
<li>Look at some of the other programs in <tt>user/</tt> to see
|
|
|
|
how you can obtain the arguments passed to a program. If the user
|
|
|
|
forgets to pass an argument, sleep should print an error message.
|
|
|
|
|
|
|
|
<li>The argument is passed as a string; you can convert it to an
|
|
|
|
integer using <tt>atoi</tt> (see user/ulib.c).
|
|
|
|
|
2019-07-24 18:26:05 +00:00
|
|
|
<li>Use the system call <tt>sleep</tt> (see user/usys.S and kernel/sysproc.c).
|
2019-07-24 18:20:27 +00:00
|
|
|
|
|
|
|
<li>Make sure <tt>main</tt> calls <tt>exit()</tt> in order to exit
|
|
|
|
your program.
|
|
|
|
|
|
|
|
<li>Add the program to <tt>UPROGS</tt> in Makefile and compile
|
|
|
|
user programs by typing <tt>make fs.img</tt>.
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>Run the program from the xv6 shell:
|
|
|
|
<pre>
|
|
|
|
$ make qemu
|
|
|
|
...
|
|
|
|
init: starting sh
|
2019-07-25 11:07:03 +00:00
|
|
|
$ sleep 10
|
2019-07-24 18:20:27 +00:00
|
|
|
(waits for a little while)
|
|
|
|
$
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>Optional: write an uptime program that prints the uptime in terms
|
2019-07-25 00:30:20 +00:00
|
|
|
of ticks using the <tt>uptime</tt> system call.
|
2019-07-24 18:20:27 +00:00
|
|
|
|
|
|
|
<h2>pingpong</h2>
|
2019-07-25 00:30:20 +00:00
|
|
|
|
2019-07-24 18:20:27 +00:00
|
|
|
<p> 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 <tt>fd[1]</tt> and
|
|
|
|
the child receives it by reading from <tt>fd[0]</tt>. After
|
|
|
|
receiving a byte from parent, the child responds with its own byte
|
|
|
|
by writing to <tt>fd[1]</tt>, which the parent then reads.
|
|
|
|
|
|
|
|
<p>Some hints:
|
|
|
|
<ul>
|
|
|
|
<li>Use <tt>pipe</tt> to create a pipe.
|
|
|
|
<li>Use <tt>fork</tt> to create a child.
|
|
|
|
<li>Use <tt>read</tt> to read from the pipe, and <tt>write</tt> to write to the pipe.
|
|
|
|
</ul>
|
2019-07-25 00:30:20 +00:00
|
|
|
|
|
|
|
<h2>primes</h2>
|
|
|
|
|
|
|
|
<p>Write a concurrent version of prime sieve using pipes. This idea
|
|
|
|
is due to Doug McIlroy, inventor of Unix pipes. The picture
|
|
|
|
halfway down <a href="http://swtch.com/~rsc/thread/">the page</a>
|
|
|
|
and the text surrounding it explain how to do it.
|
|
|
|
|
|
|
|
<p>Your goal is to use <tt>pipe</tt> and <tt>fork</tt> 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.
|
|
|
|
|
|
|
|
<p>Some hints:
|
|
|
|
<ul>
|
|
|
|
<li>Be careful to close file descriptors that a process doesn't
|
|
|
|
need, because otherwise your program will run xv6 out of resources
|
|
|
|
before the first process reaches 35.
|
|
|
|
|
|
|
|
<li>Once the first process reach 35, you should arrange that the
|
|
|
|
pipeline terminates cleanly (Hint: read will return an end-of-file
|
|
|
|
when the write-side of the pipe is closed).
|
|
|
|
</ul>
|
2019-07-24 18:20:27 +00:00
|
|
|
|
|
|
|
<h2>find</h2>
|
|
|
|
|
2019-07-24 18:26:05 +00:00
|
|
|
<p>Write a simple version of the UNIX find program: find all the files
|
2019-07-24 22:00:32 +00:00
|
|
|
in a directory tree whose name matches a string. For example if the
|
|
|
|
file system contains a file <tt>a/b</tt>, then running find as
|
|
|
|
follows should produce:
|
|
|
|
<pre>
|
|
|
|
$ find . b
|
|
|
|
./a/b
|
|
|
|
$
|
|
|
|
</pre>
|
2019-07-24 18:26:05 +00:00
|
|
|
|
|
|
|
<p>Some hints:
|
|
|
|
<ul>
|
|
|
|
<li>Look at user/ls.c to see how to read directories.
|
2019-07-24 22:00:32 +00:00
|
|
|
<li>Use recursion to run find in sub-directories.
|
|
|
|
<li>Don't recurse into "." and "..".
|
|
|
|
</ul>
|
2019-07-24 18:26:05 +00:00
|
|
|
|
2019-07-25 10:50:12 +00:00
|
|
|
<p>Optional: support regular expressions in name matching. Grep has some
|
|
|
|
primitive support for regular expressions.
|
|
|
|
|
|
|
|
<h2>xargs</h2>
|
|
|
|
|
|
|
|
<p>Write a simple version of the UNIX xargs program: read lines from
|
|
|
|
standard in and run a command for each line, supplying the line as
|
|
|
|
arguments to the command. The following example illustrates xarg's
|
|
|
|
behavior:
|
|
|
|
<pre>
|
|
|
|
$ xargs echo bye
|
|
|
|
hello too
|
|
|
|
bye hello too
|
|
|
|
<ctrl-d>
|
|
|
|
$
|
|
|
|
</pre>
|
|
|
|
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".
|
|
|
|
|
|
|
|
<p>xargs and find combine well:
|
|
|
|
<pre>
|
|
|
|
find . b | xargs grep hello
|
|
|
|
</pre>
|
|
|
|
will run "grep hello" on each file named b in the directories below ".".
|
|
|
|
|
|
|
|
<p>Some hints:
|
|
|
|
<ul>
|
|
|
|
<li>Use <tt>fork</tt> and <tt>exec</tt> system call to invoke the
|
|
|
|
command on each line of input. Use <tt>wait</tt> in the parent
|
|
|
|
to wait for the child to complete running the command.
|
|
|
|
<li>Read from stdin a character at the time until the newline
|
|
|
|
character ('\n').
|
|
|
|
<li>kernel/param.h declares MAXARG, which may be useful if you need
|
|
|
|
to declare an argv.
|
|
|
|
</ul>
|
|
|
|
|
2019-07-25 11:47:22 +00:00
|
|
|
<h2>Optional: modify the shell</h2>
|
2019-07-24 18:20:27 +00:00
|
|
|
|
2019-07-25 11:47:22 +00:00
|
|
|
There are endless ways in which the shell could be extended. Here are
|
|
|
|
some suggestions:
|
2019-07-24 22:00:32 +00:00
|
|
|
|
2019-07-25 11:47:22 +00:00
|
|
|
<ul>
|
|
|
|
|
|
|
|
<li>Modify the shell to support wait.
|
2019-07-24 18:20:27 +00:00
|
|
|
|
2019-07-25 11:47:22 +00:00
|
|
|
<li>Modify the shell to support lists of commands, separated by ";"
|
|
|
|
|
|
|
|
<li>Modify the shell to support sub-shells by implementing "(" and ")"
|
|
|
|
|
|
|
|
<li>Modify the shell to allow users to edit the command line
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
2019-07-24 18:20:27 +00:00
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
|
|
|
|
|