# 实验说明

## 实验难度

每个实验都具有相应的难度

- Easy：不到一个小时。这些锻炼通常是为后续锻炼做的热身运动。

- Moderate：1-2小时。

- Hard：超过2个小时。这些练习通常不需要很多代码，但是代码很难正确。

实验往往不需要很多行代码(几十到几百行) ，但是代码在概念上很复杂，而且细节往往很重要。所以，在你写任何代码之前，一定要完成实验室指定的阅读，通读相关文件，查阅文档(RISC-V手册等存放在了[参考页面](https://pdos.csail.mit.edu/6.828/2020/reference.html)上)。只有当你确定掌握了任务和解决方案，再开始编码。当你开始编写代码的时候，一小步一小步地实现你的解决方案(作业通常会建议如何将问题分解为更小的步骤)，并且在继续下一个步骤之前测试每个步骤是否正常工作。

## 调试技巧

确保你理解了c和指针。Kernighan和Ritchie的《c程序设计语言》一书对C语言进行了简要的描述。这里有一些有用的指针练习。除非你已经完全掌握了C语言，不要跳过或略读上面的指针练习。如果你不能真正理解C语言中的指针，你将在实验室中遭受难以言喻的痛苦，然后最终以一种艰难的方式来理解它们。相信我们，你不会想知道什么是“艰难的路”的。

一些常见的习惯用法特别值得记住:

- 如果`int *p = (int*)100`，那么`(int)p + 1`及`(int)(p + 1)`是不同的数字，第一个是101，但第二个是104。当向指针添加一个整数时，如第二种情况，整数被隐式地乘以指针指向的对象的大小。

- `p[i]`被定义为与`*(p+i)`相同，指向内存中p指向的第i个对象，当对象大于1字节时，上面所说的加法规则有利于此定义工作

虽然大多数C程序不需要在指针和整数之间进行强制转换，但操作系统经常需要这样做。每当您看到一个包含内存地址的加法时，问问自己它是整数加法还是指针加法，并确保所添加的值是否适当地相乘。

- 如果你有一个部分工作的练习，请通过提交代码来检查你的进度。如果您稍后破坏了某些东西，那么您可以回滚到您的检查点，然后以较小的步骤继续前进。要了解关于Git的更多信息，请查看[Git用户手册](http://www.kernel.org/pub/software/scm/git/docs/user-manual.html)，或者您可能会发现这个[面向计算机科学家的Git概述](http://eagain.net/articles/git-for-computer-scientists/)非常有用。

- 如果您没有通过测试，确保您了解为什么您的代码没有通过测试。插入打印(printf)语句，直到您理解正在发生的事情。

- 您可能会发现您的print语句可能会产生许多您想要搜索的输出；其中一种方法是在`script`内部运行`make qemu`（在您的机器上运行`man script`），它将所有控制台输出记录到一个文件中，然后您可以搜索该文件。别忘了退出`script`。

- 在许多情况下，print语句就足够了，但有时能够单步遍历一些汇编代码或检查堆栈上的变量是有帮助的。要在xv6中使用gdb，请在一个窗口中运行`make qemu-gdb`，在另一个窗口中运行`gdb`（或`riscv64-linux-gnu-gdb`），设置断点，后跟“`c`”（continue），xv6将一直运行，直到到达断点。（有关有用的GDB提示，请参阅[使用GNU调试器](https://pdos.csail.mit.edu/6.828/2019/lec/gdb_slides.pdf)。）

- 如果要查看编译器为内核生成的程序集是什么，或者要找出特定内核地址的指令是什么，请参阅文件`kernel.asm`，该文件在编译内核时由Makefile生成。（Makefile同时也为所有用户程序生成.asm文件。）

- 如果内核崩溃，它将打印一条错误消息，列出崩溃时程序计数器的值；您可以进行搜索`kernel.asm`找出程序计数器崩溃时在哪个函数中，或者可以运行`addr2line -e kernel/kernel pc-value`（有关详细信息，请运行`man addr2line`）。如果要获取回溯，请使用gdb重新启动：在一个窗口中运行'`make qemu-gdb`'，在另一个窗口中运行gdb（或`riscv64-linux-gnu-gdb`），在`panic`中设置断点（“`b panic`”），后跟“`c`”（continue）。当内核到达断点时，键入“bt”以获取回溯跟踪。

- 如果您的内核挂起(例如，由于死锁)或无法进一步执行(例如，由于在执行内核指令时出现页面错误)，您可以使用gdb查找挂起的位置。在一个窗口中运行“ `make qemu-gdb`”，在另一个窗口中运行 `gdb` (`riscv64-linux-gnu-gdb`) ，后跟“`c`”(continue)。当内核出现挂起时，在 `qemu-gdb` 窗口中按 `Ctrl-C` 并键入“`bt`”以获得回溯跟踪。

- qemu有一个“监视器”，允许您查询模拟机器的状态。您可以通过键入`<Ctrl>+a c`（c表示控制台）来获得它。一个特别有用的monitor命令`是info mem`，用于打印页表。您可能需要使用`cpu`命令来选择`info mem`查看哪一个核心，或者可以使用`make CPUS=1 qemu`启动qemu，以使其只有一个核心。

花时间学习上述工具是非常值得的