熟悉开发环境,对开发和调试非常关键,本节对JOS环境进行一个简单的概述,以及对GDB和QEMU的有用命令进行介绍。除了这些之外,还需要阅读GDB和QEMU手册。这些都是非常强大的工具,非常有必要去熟悉如何使用它们
1. 调试技巧
2. JOS makfile介绍
JOS GNUmakefile文件包含很多的伪目标(Phony Target),用以不同的方式运行JOS。 所有的这些目标配置QEMU来监听GDB连接(*-gdb目标也是等到GDB连接),一旦启动了QEMU,只要在当前的lab目录下运行gdb即可。在代码中提供了.gdbinit文件自动在QEMU中指向GDB,加载内核符号表,以及在16-bit和32-bit模式之间切换,退出GDB将关闭QEMU。
以下命令构建所有,并启动QEMU(包括在新窗口中启动VGA终端和当前终端中启动串口终端)。退出的话,要么通过关闭VGA窗口或者在串口中断中通过按Ctrl-c或者Ctrl-a x退出。
以下命令类似make qemu,但只在串口终端中启动Qemu,退出的话,按Ctrl-a x。这对于ssh方式登录非常有用,因为VGA窗口会消耗很大的带宽
以下命令类似make qemu,但是并不是在任何时间被动地接受GDB连接,该命令停止在第一条机器命令,然后等待GDB连接。
以下结合qemu-nox和qemu-gdb目标
(Lab 3+)运行用户程序name,例如,make run-hello运行user/hello.c
makefile也可以接收一些有用的变量,例如:
以下命令V=1表示verbose模式,打印出每条命令的执行,包括参数。
以下命令表示当任何评分测试fail的时候即停止,然后把Qemu输出到jos.out中用于检查
指定额外的参数,传递给QEMU
3. JOS生成文件
当构建JOS,makefile同时会产生一些额外的输出文件,在进行代码调试时非常的有用。
obj/boot/boot.asm, obj/kern/kernel.asm, obj/user/hello.asm, 等等 |
bootloader,kernel,和用户程序的汇编代码
obj/kern/kernel.sym, obj/user/hello.sym,等等 |
obj/boot/boot.out, obj/kern/kernel, obj/user/hello等等 |
kernel和user程序的ELF镜像,这些包含的符号信息可以被GDB使用
4. GDB常用命令介绍
更多的关于GDB的详细用法,可以参考GDB手册。以下只介绍6.828课程中用到的一些特定的GDB命令。其中的一些GDB命令在OS开发完很少使用。
停止当前机器,以及在GDB当前的指令处中断,若QEMU有很多虚拟CPU,将终止它们。
继续执行直到下一个断点或者Ctrl-c
执行一条机器指令
在给定的函数或者行设置断点
在EIP地址设置断点
确保数组和结构体的完美的打印
打印通用目的寄存器,eip,eflags和段选择子,对于更多的关于机器寄存器状态输出,参见QEMU info registers命令。
显示从虚拟地址addr开始的N个words的16进制输出,若N忽略,缺省为1,addr可以是任何的表达式。
显示从addr地址开始的N个汇编指令,使用$eip作为addr将显示当前指令指针的指令。
(Lab 3+)切换符号文件file,当GDB连接到Qemu,在虚拟机中没有进程边界的概念,所以需要告诉它使用哪个符号,缺省情况下,配置GDB使用内核符号表,obj/kern/kernel,若机器正在运行用户代码,比如hello.c,可以使用symbol-file obj/user/hello,切换到hello符号文件中。
Qemu中各个虚拟的CPU在GDB中作为一个线程,所以可以使用所有的GDB的线程相关的命令来观察和管理Qemu的虚拟CPUs。
GDB一次只关注一个线程(e.g. CPUs),该命令切换到线程n,线程编号从0开始
列出所有的线程(例如,CPUs),包括它们的状态(活动的还是终止的),以及它们处在哪个函数中。
5. QEMU常用命令介绍
CS =0008 10000000 ffffffff 10cf9a00 DPL=0 CS32 [-R-] |