实验概述¶
所有课程实验都需要 独立完成 。你应当 主动避免阅读、使用任何人/互联网上的XV6实验代码 。在实验中碰到问题很正常,发现问题时需沉着冷静,认真阅读实验指导书,查阅MIT 6.S081的官方网站以及XV6 book,尝试自己调试解决,也可以向同学/助教/老师请教调试的技巧。只有这样,你才能够得到真正的训练与收获!
关于第一次实验验收考核
我们将在第二次实验课进行现场验收:
-
验收内容 :
- Lab1:XV6与Unix实用程序
-
验收目的 :考察同学们是否是自己完成的实验代码,而不是“复制拷贝”。
-
验收形式 :助教/老师与同学们进行一对一问答
请同学们认真对待!
实验说明
该部分说明了该实验需要完成的任务,以及要求达到怎样的目标。需要注意,本章实验上手很难,但是内容简单,大家需要 耐心理清楚 实验指导书的脉络。
特别推荐同学们观看由我校OS课题组、各级学长助教们合力为大家录制的XV6讲解视频,希望能够让大家对整个XV6系统有一个更为直观的认识,推荐大家按需观看:
-
【HITSZ操作系统课程组讲解XV6(一)启动过程】
-
【HITSZ操作系统课程组讲解XV6(二)进程管理】
-
【HITSZ操作系统课程组讲解XV6(三)内存管理】
也可以观看B站上的MIT 6.S081/Fall 2020课程视频,通过学习这门课程可以让你对xv6操作系统有一个全面的认识。
1. 实验目的¶
- 认识xv6操作系统,并熟悉其运行环境。
- 复习并巩固系统调用、进程等理论知识,掌握在xv6上编写用户程序的方法,要求实现sleep、pingpong和find用户程序。
- 理解和掌握xv6的启动流程,包括资源初始化、第一个进程的诞生等,要求能够使用 gdb 以及 gdb-dashboard 分别打印出初始进程 initcode 和 init 程序的名字。
2. 实验学时¶
本实验为4学时。
3. 实验内容及要求¶
与xv6原有的实验不一样的是,本次实验需要实现3个Unix实用程序和xv6启动流程实验,并且对原实验做了修改 。这里展示的是程序功能和实验测试的最终效果,更多详细的介绍可在后续章节中阅读。为了降低难度,在实验步骤中给出了每个实验的提示。
3.1 sleep¶
为了让同学们能快速上手,我们在实验步骤中已经给出sleep程序的源码,同学们只需要按照实验步骤完成即可。sleep程序会等待用户指定的时间。请将代码写在user/sleep.c文件中。运行效果应该如下:

输入命令后,命令行会 ”暂停“ 一段时间 (10个ticks,ticks由内核定义,一个tick大概100ms),然后输出"(nothing happens for a little while)"。
在xv6-oslab24-hitsz中,执行下面指令./grade-lab-util sleep,测试程序:

关于虚拟机实验环境提示/usr/bin/env: 'python': No such file or directory问题
虚拟机实验环境安装的是python3,只需让系统把python3识别为python即可,执行以下命令:
sudo ln -s /usr/bin/python3 /usr/bin/python
这个命令会在/usr/bin目录下创建一个python到python3的符号链接,之后再运行./grade-lab-util sleep就能正常调用 Python 解释器了。
3.2 pingpong¶
你需要在xv6上实现pingpong程序,即两个进程在管道两侧来回通信。你需要使用两个管道(可以命名为c2f和f2c),其中c2f用于子进程向父进程传输数据,f2c用于父进程向子进程传输数据。(思考一下能不能只用一个管道实现呢?)
任务要求如下:
-
父进程向管道中写入数据,子进程从管道将其读出并打印
<pid>: received ping from pid <father pid>,其中<pid>是子进程的进程ID,<father pid>是父进程的进程ID。 -
子进程从父进程收到数据后,通过写入另一个管道向父进程传输数据,然后由父进程从该管道读取并打印
<pid>: received pong from pid <child pid>,其中<pid>是父进程的进程ID,<child pid>是子进程的进程ID。
请将代码写在user/pingpong.c文件中。然后运行XV6,在XV6命令行中输入如下命令,pingpong程序运行效果如下:(注意不要加尖括号)

也可以到xv6-oslab24-hitsz项目目录,执行下面指令./grade-lab-util pingpong,测试程序:

3.3 find¶
你需要在xv6上实现用户程序find,即在目录树中查找名称与字符串匹配的所有 文件或目录,输出文件的相对路径。该程序的 命令格式为“find <path> <name>” (注:这与Linux中的find命令格式略有不同,Linux中的对应格式为find <path> -name <name>)。请将代码写在user/find.c文件中。
任务要求如下:
- 在根目录新建 文件b (echo > b这个命令的效果就是清空(或创建并清空)文件b)时,当cwd(Current Working Directory)为根目录时,在根目录下查询b的输出效果应该如下:

- 在根目录新建 目录b (mkdir b 这个命令用于创建一个名为 b 的新目录(文件夹))时,当cwd(Current Working Directory)为根目录时,在根目录下查询b的输出效果应该如下:

- 另外,你还应当实现 递归查询 ,当要查询的目录或文件
target在根目录的某个子文件夹中时,你也应该将结果显示出来

也可以到xv6-oslab24-hitsz项目目录,执行下面指令./grade-lab-util find,测试程序

如果上述3个程序(sleep、pingpong、find)都能正常运行,可以到xv6-oslab24-hitsz项目目录,执行make grade指令测试:

3.4 xv6启动流程实验¶
Tip
实验过程中可以结合观看由我校录制的XV6讲解视频HITSZ操作系统课程组讲解XV6(⼀)启动过程视频 以及 使用gdb调试xv6启动流程(1)、使用gdb调试xv6启动流程(2),这会帮助你更好的理解xv6的启动流程和学会使用GDB调试。
学会使用 gdb 以及 gdb-dashboard 调试 xv6 启动流程,在调试过程中需要在两处地方使用 p cpus[$tp]->proc->name($tp 是 tp 寄存器的值,xv6 使用它作为 cpu 的编号,这串式子其实相当于 myproc() 函数,但不知为何远程平台 gdb 不支持调用函数)打印出当前 proc 结构体的 name,分别打印出初始进程 initcode 和 init 程序的名字(打印的历史输出会保存在 gdb-dashboard 的 history 区域)。
最后需要提交一个 gdb 命令脚本文件(记得 git add 和 git commit 这个文件),命名为 commands.gdb,要求在 gdb 调试中使用 source commands.gdb 执行脚本后,会在 gdb-dashboard 的 history 区域中显示如下内容。

Tip
关于 gdb 命令脚本如何导出,请参考 GDB调试指南中的“4.2.2 历史与脚本”一节。
最终的 commands.gdb 文件(不限制长度,长度不算在分数内,但最短仅需6行,同学们可以尝试)应该类似这样:
...
p cpus[$tp]->proc->name # 应该先打印出 "initcode"
...
p cpus[$tp]->proc->name # 再打印出 "init"
da # 使用命令刷新 dashboard 并将上一个输出显示在 history 区域