Loading...

Lab: Xv6 and Unix utilities

本实验室将帮助熟悉xv6及其系统调用

1.Boot xv6 (easy)

配置环境: 详细请见:Lab0

获取实验室的xv6源代码并签出util分支

1
2
3
4
5
$ git clone git://g.csail.mit.edu/xv6-labs-2021

$ cd xv6-labs-2021
$ git checkout util


xv6-labs-2021存储库与本书的xv6-riscv略有不同。它主要是添加一些文件。如果你好奇,可以看看git日志:

1
$ git log

本次作业和后续实验作业所需的文件使用Git版本控制系统分发。上面你切换到一个分支(git checkout util),其中包含为这个实验室定制的xv6版本。要了解有关Git的更多信息,请查看Git用户手册(Git user’s manual),或者你可能会发现这个面向cs的Git概述很有用。Git允许你跟踪对代码所做的更改。例如,如果你完成了其中一个练习,想检查进度,可以执行以下命令提交修改:

1
$ git commit -am 'my solution for util lab exercise 1'

Build and run xv6:

1
$ make qemu

产生如下报错该怎么解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
user/sh.c:58:1: error: infinite recursion detected [-Werror=infinite-recursion]
58 | runcmd(struct cmd *cmd)
| ^~~~~~
user/sh.c:89:5: note: recursive call
89 | runcmd(rcmd->cmd);
| ^~~~~~~~~~~~~~~~~
user/sh.c:109:7: note: recursive call
109 | runcmd(pcmd->left);
| ^~~~~~~~~~~~~~~~~~
user/sh.c:116:7: note: recursive call
116 | runcmd(pcmd->right);
| ^~~~~~~~~~~~~~~~~~~
user/sh.c:95:7: note: recursive call
95 | runcmd(lcmd->left);
| ^~~~~~~~~~~~~~~~~~
user/sh.c:97:5: note: recursive call
97 | runcmd(lcmd->right);
| ^~~~~~~~~~~~~~~~~~~
user/sh.c:127:7: note: recursive call
127 | runcmd(bcmd->cmd);
| ^~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make: *** [user/sh.o] Error 1

解决方法:在xv6-labs-2021/user/sh.c文件中, runcmd函数上面添加设置特殊属性的宏

1
2
3
4
__attribute__((noreturn))
void
runcmd(struct cmd *cmd)
{

如果在提示符下输入ls,您应该看到类似以下的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.              1 1 1024
.. 1 1 1024
README 2 2 2059
xargstest.sh 2 3 93
cat 2 4 24256
echo 2 5 23080
forktest 2 6 13272
grep 2 7 27560
init 2 8 23816
kill 2 9 23024
ln 2 10 22880
ls 2 11 26448
mkdir 2 12 23176
rm 2 13 23160
sh 2 14 41976
stressfs 2 15 24016
usertests 2 16 148456
grind 2 17 38144
wc 2 18 25344
zombie 2 19 22408
console 3 20 0

这些是mkfs包含在初始文件系统中的文件;大多数是可以运行的程序。你刚刚运行了其中一个:ls。

xv6没有ps命令,但如果你键入Ctrl-p,内核将打印每个进程的信息。如果你现在尝试一下,会看到两行代码:一行用于init,另一行用于sh。



ps 命令是 Linux/Unix 系统中一个非常重要和常用的进程查看和控制命令, process status 的缩写,它可以用来显示当前系统的进程状态。


退出qemu输入:Ctrl-a x。

2.sleep (easy)

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

一些暗示:

  • 在开始编写代码之前,请阅读此书的第1章
  • 看看user/中的其他程序(例如user/echo.c、user/grep.c和user/rm.c),看看如何获得传递给程序的命令行参数。
  • 如果用户忘记传递参数,sleep应该打印一条错误消息
  • 命令行参数是一个字符串;你可以使用atoi将其转换为整数(参见user/ulib.c)
  • 使用系统调用sleep
  • 有关实现sleep系统调用的xv6内核代码,请参见kernel/sysproc, user/user.h是用户程序中可调用的sleep的C定义,user/usys.S表示从用户代码跳转到内核休眠的汇编代码。
  • 确保main调用exit()以退出程序
  • 在Makefile中添加睡眠程序;完成这一步后,make qemu将编译程序,这样就可以在xv6 shell中运行它了。

关于上面提到的user/echo.c,user/grep.c,user/rm.c,user/ulib.c,kernel/sysproc, user/user.h,user/usys.S需要一一进行解读