fengzhao / xv6-2022

2022 xv6 study.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Lab: Xv6 and Unix utilities

本实验将使您熟悉xv6及其系统调用。

sleep

为xv6实现UNIX程序sleep. 您的sleep应该暂停用户指定的ticks数。tick是由xv6内核定义的时间概念,即来自计时器芯片的两次中断之间的时间。您的解决方案应该在文件user/sleep.c中。

一些提示

  • 在开始之前, 先阅读xv6 book的第一章

  • 查看user/中的其他一些程序(例如,user/echo.c, user/grep.cuser/rm.c),了解如何获取传递给程序的命令行参数。

  • 如果用户忘记传递参数,sleep应该打印一条错误消息。

  • 命令行参数作为字符串传递; 您可以使用atoi将其转换为整数(参见user/ulib.c)。

  • 使用系统调用sleep

  • 参见kernel/sysproc.c获得实现sleep系统调用的xv6内核代码(请查找sys_sleep),参见user/user.h获得从用户程序调用sleep的C定义,参见user/usys.S表示从用户代码跳转到内核休眠的汇编程序代码。

  • main应该调用exit(0)来结束

  • sleep程序添加到Makefile中的UPROGS. 完成此操作后,make qemu将编译您的程序,您将能够从xv6 shell运行它。

完成后你可以运行程序

$ make qemu
...
init: starting sh
$ sleep 10
(nothing happens for a little while)
$

如果您的程序在如上所示运行时暂停,那么您的解决方案就是正确的。运行make grade,看看你是否真的通过了sleep测试。

$ ./grade-lab-util sleep

或者, 可以(make grade会运行所有测试)

make GRADEFLAGS=sleep grade

pingpong (easy)

编写一个程序,利用UNIX系统调用,通过一对管道在两个进程之间“ping-pong”一个字节。父进程应该向子进程发送一个字节; 子进程应该打印“: received ping”,其中是它的进程ID,将该字节写入管道到父进程,然后退出;父进程应该从子进程读取字节,打印": received pong",然后退出。你的解决方案应该在文件user/pingpong.c中。

一些提示

  • 使用pipe创建一个管道
  • 使用fork创建一个儿子进程
  • 使用read从管道读, 使用write写入一个管道
  • 使用getpid获取进程的id号
  • 同样添加到Makefile
  • xv6上的用户程序只能使用一组有限的库函数。你可以在user/user.h中看到这个列表;源(除了系统调用)在user/ulib.c、user/printf.c和user/umalloc.c中。

primes (moderate)/(hard)

使用管道(pipe)编写一个prime sieve的并发版本。这个想法要归功于Unix管道的发明者Doug McIlroy。this page中间的图片和周围的文字解释了如何做到这一点。你的解决方案应该在文件user/primes.c中。

你的目标是使用pipe和fork来设置管道。第一个进程将数字2 ~ 35输入到管道中。对于每个质数,你可以安排创建一个进程,通过一个管道从它的左邻居读取数据,并通过另一个管道向它的右邻居写入数据。由于xv6的文件描述符和进程数量有限,第一个进程可以在35处停止。

find (moderate)

编写一个Unix find的简单版本. 查找目录树中具有特定名称的所有文件。你的解决方案应该在文件user/find. d中。

  • 查看user/ls.c了解如何读取目录

  • 你需要用到递归来遍历目录树,但是不要对"."和”..“进行递归

  • 对文件系统的更改会在qemu运行时持续保存;要得到一个干净的文件系统,运行make clean,然后make qemu。

  • 你需要用到C字符串。但是请使用strcmp()来比较字符串

  • 将程序添加到Makefile中的UPROGS中。

[input]
echo > b
mkdir a
echo > a/b
mkdir a/aa
echo > a/aa/b
find . b
[output]
./b
./a/b
./a/aa/b

xargs (moderate)

编写一个简单版本的UNIX xargs程序: 它的参数描述了要运行的命令,它从标准输入中读取行,然后针对每一行执行该命令,并将该行添加到命令的参数后面。你的解决方案应该在文件user/xargs.c中。

例如, 下面是一个例子

$ echo hello too | xargs echo bye
bye hello too
$

注意,这里的命令是"echo bye",附加的参数是"hello too",所以命令是"echo bye hello too",输出结果是"bye hello too"。 请注意,UNIX上的xargs进行了优化,它将一次向命令提供更多的参数。我们不期望你进行这种优化。为了让xargs在UNIX上按照我们希望的方式运行,请将-n选项设置为1。例如

$ (echo 1 ; echo 2) | xargs -n 1 echo
1
2
$
  • 使用fork和exec来对每一行输入调用该命令。在父进程中使用wait等待子进程完成命令。
  • 要读取单个输入行,每次读取一个字符,直到出现换行符('\n')。
  • kernel/param.h声明了MAXARG,如果你需要声明argv数组,它可能会很有用。
  • 将程序添加到Makefile中的UPROGS中。

这里有一个xargs, find, grep组合的例子

$ find . b | xargs grep hello

将对“.”目录下的每个名为b的文件运行“grep hello”。

请运行shell脚本xargstest.sh。如果你的解决方案产生以下输出,说明它是正确的:

$ make qemu
...
init: starting sh
$ sh < xargstest.sh
$ $ $ $ $ $ hello
hello
hello
$ $

你可能需要返回去修复find程序中的bug。输出中有很多$, 因为xv6 shell没有意识到它处理的是文件中的命令,而不是控制台中的命令,因此文件中的每个命令都会打印一个$。

About

2022 xv6 study.

License:Other


Languages

Language:C 85.5%Language:Python 7.7%Language:Makefile 3.4%Language:Assembly 3.1%Language:Perl 0.2%Language:Shell 0.0%Language:Emacs Lisp 0.0%