常见问题及解答 ¶
首先需要明确的是,本次实验中的所有操作都不应该经由 Windows 中的文件系统,请直接在虚拟机或 Linux 物理机中直接完成。
禁止直接 fork 本课程的 github 仓库
本课程要求同学们严格遵循诚信守则,禁止同学之间互相抄袭实验代码。如需建立私人 github 仓库,请将本课程仓库 clone 到本地之后,上传到自己的 private repo。禁止直接 fork 本课程的 github 仓库或直接将本课程实验相关内容上传到任何 public repo。
实验提交要求 ¶
实验提交时需要同时提交代码压缩包和实验报告两个文件。
实验报告要求上传 pdf 文件,其中需要包含以下内容:
- 实验内容及简要原理介绍
- 实验具体过程与代码实现
- 实验结果与分析
- 实验中遇到的问题及解决方法
- 思考题与心得体会
- 对实验指导的建议(可选)
Tip
- 在代码实现部分重点展示设计思路和核心部分代码即可,不需要大段粘贴代码
- 如要展示代码,需以非纯文本的形式展示(需要使用代码块)
- 思考题占有一定的分值,需要认真回答
- 请保持实验报告清晰、简洁
为什么我把 Linux 源码放在共享文件夹或 wsl2 的 /mnt
下编译不出来?¶
这种情况下,Linux 在使用 Windows 上的文件系统。请使用 wget
等工具将 Linux 源码下载至容器内目录而非共享目录或 /mnt
目录下的任何位置,然后执行编译。
为什么 QEMU & GDB 使用 si
单指令调试遇到模式切换时无法正常执行?¶
在遇到诸如mret
, sret
等指令造成的模式切换时,si
指令会失效,可能表现为程序开始不停跑,影响对程序运行行为的判断。
一个解决方法是在程序预期跳转的位置打上断点,断点不会受到模式切换的影响,比如:
(gdb) i r sepc
sepc 0x8000babe
(gdb) b * 0x8000babe
Breakpoint 1 at 0x8000babe
(gdb) si # 或者使用 c
Breakpoint 1, 0x000000008000babe in _never_gonna_give_you_up ()
...
这样就可以看到断点被触发,可以继续调试了。
为什么我不能在 GDB 中使用 next
或者finish
? ¶
这两条命令都依赖在内核中添加的调试信息,可以通过 menuconfig
进行配置添加。我们在实验中没有对这部分内容作要求,可以自行 Google 探索。
为什么我在内核中添加了 debug 信息,但是还是没法使用 next
或者finish
? ¶
可能你在配置内核时已经添加了调试信息,但是并没有在QEMU 运行的其他部分添加。例如 SRAM 中对 march
进行配置的过程,以及 opensbi 中的所有部分,都缺少调试信息。所以才无法按照函数的层级进行调试。我们在实验中没有对这部分内容作要求,可以自行 Google 探索。
为什么 Lab1 中我的 C 语言函数的参数无法正确传入?¶
确认自己是否在 head.S
里的 _start
函数中正确设置了 sp
,正常情况下它的值应该是 0x8020XXXX
。未设置或设置错 sp
会使栈上的值不正确且无法写入。
Tip
注意检查是否将 head.S
里的 .section
改为 .text.init
,如果不改的话 _traps
和 _start
都在 .text.entry
段,此时 _traps
会被放置到 0x80200000
处,导致其先于 _start
执行;而此时还未设置 sp
,故传参时会出现混乱(具体表现为 trap_handler
的所有参数均显示 2^64-1
不会找 Lab1 的 syscall table 怎么办?¶
主要有两种方法,一种是安装该架构的交叉编译工具链并编译得到预处理产物,另一种则是在某些文件中直接就有现成的 syscall table. 无论选用哪种方法都要善用搜索,查找系统调用具体放在哪个文件中。可以参考这篇文章。
Tip
或许可以直接去 arch
对应架构文件夹下搜索关键词?
如何升级到 Ubuntu 24.04 ¶
请按照 How to upgrade - Ubuntu 或 DebianUpgrade - Debian Wiki 的说明进行升级,所需命令概括如下(使用两种方式之一即可
-
使用 Ubuntu 特有的
do-release-upgrade
命令: -
使用 Debian 标准的升级流程:
升级完成后,务必尽快重启,不论是物理机还是虚拟机(WSL、Docker
不知道如何计算 Lab3 建立映射时所需的虚拟地址 va
和大小 sz
?¶
在 vmlinux.lds
中有_stext
, _srodata
等符号,可以在代码里这样来声明它:extern char _stext[]
,这样就可以通过 _stext
获得其所在虚拟地址 va
,并且可以通过两个段的开头符号做减法获得段的大小 sz
。