238 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <html>
 | |
| <head>
 | |
| <title>Lab: xv6</title>
 | |
| <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>
 | |
| 
 | |
| <p>Implement the UNIX program sleep for xv6; your sleep should pause
 | |
|   for a user-specified number of ticks.
 | |
| 
 | |
| <p>Some hints:
 | |
|   <ul>
 | |
|     <li>Look at some of the other programs in <tt>user/</tt> 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.
 | |
| 
 | |
|     <li>The command-line argument is passed as a string; you can convert it to an
 | |
|       integer using <tt>atoi</tt> (see user/ulib.c).
 | |
| 
 | |
|     <li>Use the system call <tt>sleep</tt> (see user/usys.S and kernel/sysproc.c).
 | |
| 
 | |
|     <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
 | |
|       $ sleep 10
 | |
|       (waits for a little while)
 | |
|       $
 | |
|     </pre>
 | |
| 
 | |
|   <p>Optional: write an uptime program that prints the uptime in terms
 | |
|     of ticks using the <tt>uptime</tt> system call.
 | |
| 
 | |
| <h2>pingpong</h2>
 | |
|     
 | |
| <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>
 | |
|     
 | |
| <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>
 | |
| 
 | |
| <h2>find</h2>
 | |
| 
 | |
| <p>Write a simple version of the UNIX find program: find all the files
 | |
|   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>
 | |
|   
 | |
| <p>Some hints:
 | |
|   <ul>
 | |
|     <li>Look at user/ls.c to see how to read directories.
 | |
|     <li>Use recursion to run find in sub-directories.
 | |
|     <li>Don't recurse into "." and "..".
 | |
|   </ul>
 | |
| 
 | |
| <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>
 | |
| 
 | |
| <h2>Optional: modify the shell</h2>
 | |
| 
 | |
| There are endless ways in which the shell could be extended. Here are
 | |
| some suggestions:
 | |
| 
 | |
| <ul>
 | |
|   
 | |
| <li>Modify the shell to support wait.
 | |
|   
 | |
| <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>
 | |
| 
 | |
| </body>
 | |
| </html>
 | |
| 
 | |
| 
 | 
