$ git clone git://g.csail.mit.edu/xv6-labs-2020 Cloning into 'xv6-labs-2020'... ... $ cd xv6-labs-2020 $ git checkout util Branch 'util'set up to track remote branch 'util' from 'origin'. Switched to a new branch 'util'
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.
sleep
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:
Before you start coding, read Chapter 1 of the xv6 book.
Look at some of the other programs in (e.g. user/echo.c, user/grep.c, user/rm.c ) to see how you can obtain the command-line arguments passed to a program.
n = 0; while('0' <= *s && *s <= '9') n = n*10 + *s++ - '0'; return n; }
Use the system call sleep.
See kernel/sysproc.c for the xv6 kernel code that implements the sleep system call (look for sys_sleep), user/user.h for the C definition of callable from a user program, and user/usys.S for the assembler code that jumps from user code into the kernel for sleep.
我们实现的user/sleep.c属于user space的函数,他通过调用system call sleep实现他的功能。在下一个lab会知道如何从user space跳转到kernel space
Passing arguments from user-level functions to kernel-level functions cannot be done in XV6. XV6 has its own built-in functions for passing arguments into a kernel function. For instance, to pass in an integer, the argint() function is called.
argint(0, &pid);
… to get the first argument which is the Process ID, and:
argint(1, &pty);
Make sure main calls exit() in order to exit your program.
最后加一条exit(0) .
Add your sleep program to UPROGS in Makefile; once you’ve done that, make qemu will compile your program and you’ll be able to run it from the xv6 shell.
Run the program from the xv6 shell:
$ make qemu ... init: starting sh $ sleep 10 (nothing happens for a little while) $
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:
$ ./grade-lab-util sleep
This will run the grade tests that match “sleep”. Or, you can type:
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 should send a byte to the child; the child should print <pid>: received ping, where pid is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print <pid>: received pong, and exit. Your solution should be in the file user/pingpong.c.
Some hints:
Use pipe to create a pipe.
Use fork to create a child.
Use read to read from the pipe, and write to write to the pipe.
Use getpid to find the process ID of the calling process.
Add the program to UPROGS in Makefile.
User programs on xv6 have a limited set of library functions available to them.
Run the program from the xv6 shell and it should produce the following output:
$ make qemu ... init: starting sh $ pingpong 4: received ping 3: received pong $
Your solution is correct if your program exchanges a byte between two processes and produces output as shown above.
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.
voidprimes(){ p = read from left // 从左边接收到的第一个数一定是素数 if (fork() == 0): primes() // 子进程,进入递归 else: loop: n = read from left // 父进程,循环接收左边的输入 if (p % n != 0): write n to right // 不能被p整除则向右输出 }
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.
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.
The following example illustrates xarg’s behavior:
$echo hello too | xargs echobye 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”.
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
$echo"1\n2" | xargs -n 1 echo line line 1 line 2 $
我感觉这个命令的意思是从标准输入读取数据作为后面命令的参数
Some hints:
Use fork and exec to invoke the command on each line of input. Use wait in the parent to wait for the child to complete the command.
To read individual lines of input, read a character at a time until a newline (‘\n’) appears.
kernel/param.h declares MAXARG, which may be useful if you need to declare an argv array.
#define MAXARG 32 // max exec arguments
Add the program to UPROGS in Makefile.
Changes to the file system persist across runs of qemu; to get a clean file system run make clean and then make qemu.
xargs, find, and grep combine well:
$ find . b | xargs grep hello
will run “grep hello” on each file named b in the directories below “.”.