实验:系统调用

在上一个实验中,你使用系统调用编写了几个工具。在本实验中,你将向xv6添加一些新的系统调用,这将帮助你理解它们是如何工作的,并让你了解xv6内核的一些内部机制。你将在后续实验中添加更多的系统调用。

在开始编码之前,阅读xv6书的第2章,以及第4章的4.3和4.4节,以及相关源文件:

要开始实验,切换到syscall分支:

  $ git fetch
  $ git checkout syscall
  $ make clean
  

如果你运行make grade,你会看到评分程序无法执行tracesysinfotest。你的任务是添加必要的系统调用和stub使它们能够工作。

系统调用跟踪

在本作业中,你将添加一个系统调用跟踪功能,这在调试后续实验时可能会对你有帮助。你将创建一个新的trace系统调用来控制跟踪。它应该接受一个参数,一个整数"mask",其位指定要跟踪哪些系统调用。例如,要跟踪fork系统调用,程序调用trace(1 << SYS_fork),其中SYS_fork是来自kernel/syscall.h的系统调用号。你必须修改xv6内核,在每个系统调用即将返回时打印一行,如果该系统调用的号在mask中被设置的话。该行应包含进程id、系统调用的名称和返回值;你不需要打印系统调用参数。trace系统调用应该为调用它的进程及其后续fork的任何子进程启用跟踪,但不应影响其他进程。

我们提供了一个trace用户级程序,它在启用跟踪的情况下运行另一个程序(参见user/trace.c)。完成后,你应该看到如下输出:

$ trace 32 grep hello README
3: syscall read -> 1023
3: syscall read -> 966
3: syscall read -> 70
3: syscall read -> 0
$
$ trace 2147483647 grep hello README
4: syscall trace -> 0
4: syscall exec -> 3
4: syscall open -> 3
4: syscall read -> 1023
4: syscall read -> 966
4: syscall read -> 70
4: syscall read -> 0
4: syscall close -> 0
$
$ grep hello README
$
$ trace 2 usertests forkforkfork
usertests starting
test forkforkfork: 407: syscall fork -> 408
408: syscall fork -> 409
409: syscall fork -> 410
410: syscall fork -> 411
409: syscall fork -> 412
410: syscall fork -> 413
409: syscall fork -> 414
411: syscall fork -> 415
...
$   

在上面的第一个例子中,trace调用grep只跟踪read系统调用。32是1<<SYS_read。在第二个例子中,trace运行grep并跟踪所有系统调用;2147583647的低31位全部被设置。在第三个例子中,程序没有被跟踪,所以没有打印跟踪输出。在第四个例子中,usertestsforkforkfork测试的所有后代的fork系统调用正在被跟踪。如果你的程序行为如上所示(尽管进程ID可能不同),则你的解决方案是正确的。

一些提示:

Sysinfo

在本作业中,你将添加一个系统调用sysinfo,用于收集正在运行的系统的信息。该系统调用接受一个参数:一个指向struct sysinfo的指针(参见kernel/sysinfo.h)。内核应该填写这个结构体的字段:freemem字段应设置为空闲内存的字节数,nproc字段应设置为state不是UNUSED的进程数。我们提供了一个测试程序sysinfotest;如果它打印"sysinfotest: OK",则你通过了本作业。

一些提示:

提交实验

实验到此完成。确保你通过了所有make grade测试。如果本实验有问题,别忘了在answers-lab-name.txt中写下你的答案。提交你的更改(包括添加answers-lab-name.txt),然后在实验目录中输入make handin来提交你的实验。

花费时间

创建一个新文件time.txt,在其中放入一个整数,表示你花在本实验上的小时数。别忘了git addgit commit该文件。

提交

你将使用
提交网站提交你的作业。在提交任何作业或实验之前,你需要从提交网站申请一次API密钥。

在提交实验的最终更改之后,输入make handin来提交你的实验。

$ git commit -am "ready to submit my lab"
[util c2e3c8b] ready to submit my lab
 2 files changed, 18 insertions(+), 2 deletions(-)

$ make handin
tar: Removing leading `/' from member names
Get an API key for yourself by visiting https://6828.scripts.mit.edu/2020/handin.py/
Please enter your API key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 79258  100   239  100 79019    853   275k --:--:-- --:--:-- --:--:--  276k
$
make handin会将你的API密钥存储在myapi.key中。如果你需要更改API密钥,只需删除此文件,然后让make handin重新生成(myapi.key不能包含换行符)。

如果你运行make handin时有未提交的更改或未跟踪的文件,你将看到类似以下的输出:

 M hello.c
?? bar.c
?? foo.pyc
Untracked files will not be handed in.  Continue? [y/N]
检查上述行,确保你的实验解决方案所需的所有文件都被跟踪,即不在以??开头的行中列出。你可以使用git add filenamegit跟踪你创建的新文件。

如果make handin不能正常工作,请尝试修复curl或Git命令的问题。或者你可以运行make tarball。这将为你制作一个tar文件,然后你可以通过我们的web界面上传。

可选挑战练习