1.panic(“Remap”) 找不到原因

这个问题算是困扰我一天多了, 一开始还想问一下chatgpt 如何解决xv6 panic remap的问题, 但是尝试无果之后还是放弃了. 然后疯狂用gdb-dashboard折腾调试, 发现还是没有VSCode来得实在, 所以最后还是在VSCode下面debug, 之所以浪费了这么多时间的问题在于不太了解这个bug生成的原因, 也没有很好的思路应对. 主要还是因为没有很好的手段可以打印页表, 如果可以打印出我关心的页表形式,我估计就可以省下很多的时间. 还有一点就在于整体页表的结构还是不太熟悉,比如虚拟地址/物理地址/PTE的flags等, 算是了解 但没有很深刻的印象, 所以也导致了这个bug花了很长的一段时间.

最后还是通过疯狂使用vmprint 来解决这个问题, 当然还引入了PTE_T 这种自创的flags 来打印, 首先我们可以先明确一个点就是只有三级页表才有PTE_U的这个flags , 因此 如果你想打印

2. 为什么Makefile 没有关于用户程序生成*.o文件的语句

这个问题是一个B站粉丝问的, 一开始我看Makefile 确实没有对应的语句, 然后就去问chatgpt 还好chatgpt解答了我的疑问,答案贴在了ourdiz上

这其实是涉及到Makefile通配符的概念, 你看到_% 这里指的是用户程序的二进制可执行文件, 那我们如何得到二进制可执行文件呢? 它依赖了后面两项%.o和$(UILIB), makefile 就会去找%.o这个文件, 发现并没有生成%.o 这个文件 , Makefile就会尝试去编译这个%.c得到%.o!! Makefile会通过自动化变量和隐式规则来推导出依赖关系。

当你在 xv6 中编写一个用户程序时,你只需要编写一个源代码文件,然后将其编译成一个目标文件。这个目标文件是一个静态链接的可执行文件,它包含了该程序的所有代码和数据,没有外部依赖,因此不需要在 Makefile 中显式地列出依赖关系。


举个例子: Makefile 可以自动编译 xv6 的用户程序,是因为这些程序没有外部依赖,是因为 Makefile 有一些默认的隐式规则可以推导出目标文件和源文件之间的依赖关系,并且根据这些依赖关系自动执行编译和链接操作。当你在 Makefile 中指定一个目标文件时,例如 sh.o,Make 会根据默认的隐式规则来推导出 sh.o 和 sh.c 文件之间的依赖关系,并根据需要自动执行编译操作。这个默认的隐式规则如下所示:

1
2
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

3. 为什么xv6正常运行 但是看起来确实毫无输出呢?

这也是一个很奇怪的bug, 他的表现是sh进程正常运行, kernel也是正常load, 但是printf的内容不会显示到stdout, 所以很疑惑

4. Xv6 panic unmapped 找不到原因

这个主要问题还是写代码不够细心, 其次就是log 打得不够好, 本来已经定位到问题发生的地方了, 但是由于自己加的FLAG 并没有很好的覆盖,所以导致这个问题也debug了比较长的时间. bug出现的原因是因为

1
2
3
if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0 || kvmalloc(p->kernel_pgtable, sz, sz+n) == 0) {
      return -1;
    }

kvmalloc在使用sz的时候已经被更新过一次了, 而不是原来的值, 这导致了 用户页表映射的map是连续的从0-20page, 而用户的内核页表是从0-3、30-35的页表,是不连续的, 导致最后在exec dealloc pagetable的时候 出现了unmapped的情况.

5. freeproc 的时候 panic (“freewalk: leaf”)

这个是因为freewalk 并不知道你free的是用户页表, 他只会清空所有页表的所有内容, 所以当你使用uvmfree(p->kernel_pagetable) 的时候它就会试图释放内核的二级页表, 但是这时候内核的三级页表还是没有被释放的, 所以就会出现这种情况.

0%