operating system

xv6 是 MIT 设计的一个教学型操纵系统。xv6 需要在 qemu 仿真机上运行,所以也要下载 qemu。本人的实验环境是 ubuntu 18

  1. 安装 qemu

    sudo apt-get install qemu
    
  2. 下载 xv6-rev9 ,本人学习的版本就是 rev9

    wget https://github.com/mit-pdos/xv6-public/archive/xv6-rev9.zip
    unzip xv6-rev9.zip
    cd xv6-rev9
    make 
    make qemu-nox
    

    运行上面的指令若没有出错即可。按 ctrl + a,再按 c,再按 q 退出。

使用系统

执行 make make-nox 进入虚拟机。一步步执行下面指令,查看变化

ls
cat README
echo hello

其实就是一些 shell 指令。其他指令和普通的 shell 差不多,自行尝试。

通过 ctrl + p 查看进程信息(由 proc.c 文件中的 procdump() 内核函数实现)。可以看到 sleep 进程后面跟着一串数字,代表调用栈地址。

通过 addr2line -e kernel address 查看源代码位置。最多显示 10 个地址(查看 proc.c源码),通过逐个检查,可以还原进程阻塞前的函数调用嵌套情况。

在系统上运行简单应用

你可以在 main.c 中修改输出语句,重新生成映像,查看输出,标志着你开始修改操作系统了。

接下来创建自己的用户程序,新建 hello-world.c 文件,写入

#include "types.h"
#include "stat.h"
#include "user.h"

int main(){
    // 这个 printf 函数里的 1 表示标准输出文件,0 表示标准输入文件,2 表示出错文件
	printf(1, "hello world!\n");
	exit();
}

上述代码中引用了 xv6 的头文件,这个程序只做简单的输出。

然后重新编辑 Makefile ,在 UPROGS 添加 _hello-world\make 后,进入仿真机 ls 查看会多一个应用。 注意查看 make 后的输出,可以看到触发了 gcc 编译、 ld 链接、objdump 反汇编以及 ./mkfs 文件系统生成工具。

执行 hello-world 查看输出。

调试

gdb 调试 qemu 分两种,一种是调试仿真机 qemu 的代码,一种是远程调试仿真机中运行的代码,我们调试后者。

  1. 调试服务器启动

    make qemu-nox-gdb
    
  2. 启动 gdb

    由于源码提供了 .gdbinit 源码, 新建 ~/.gdbinit 文件,添加下面一行

    set auto-load safe-path /
    

    然后执行 gdb kernel -silent 进入调试,而无需执行 target remote 指令。

  3. 开始调试

    执行 c 命令,开始内核执行。看到 xv6 系统启动并执行 shell 的界面。

  4. 多核调试

    重新进入调试,一步步执行以下代码

    b main
    c
    执行多个 n 直到看见 startothers()
    info threads     // 可以看见 cpu1 还没有启动
    n
    info threads     // * 表示当前线程,控制 cpu0
    thread 2         // 切换线程,控制 cpu1
    

    接下来,停止调试,修改 Makefile 中的 CPUS := 2 (在 param.h 可以修改最多 CPU 个数) ,将 CPU 修改为 3 或者 4,重新生成 xv6 的内核映像。观察启动时打印的信息变化,然后用 gdb 将各个处理器所执行的代码分别停在 scheduler() 的不同指令处(或者你感兴趣的其他代码处),并用 info threads 查看线程的数量是否和预期的一致。