项目组成

lab1的整体目录结构如下所示:

  1. .
  2. ├── boot
  3. ├── asm.h
  4. ├── bootasm.S
  5. └── bootmain.c
  6. ├── kern
  7. ├── debug
  8. ├── assert.h
  9. ├── kdebug.c
  10. ├── kdebug.h
  11. ├── kmonitor.c
  12. ├── kmonitor.h
  13. ├── panic.c
  14. └── stab.h
  15. ├── driver
  16. ├── clock.c
  17. ├── clock.h
  18. ├── console.c
  19. ├── console.h
  20. ├── intr.c
  21. ├── intr.h
  22. ├── kbdreg.h
  23. ├── picirq.c
  24. └── picirq.h
  25. ├── init
  26. └── init.c
  27. ├── libs
  28. ├── readline.c
  29. └── stdio.c
  30. ├── mm
  31. ├── memlayout.h
  32. ├── mmu.h
  33. ├── pmm.c
  34. └── pmm.h
  35. └── trap
  36. ├── trap.c
  37. ├── trapentry.S
  38. ├── trap.h
  39. └── vectors.S
  40. ├── libs
  41. ├── defs.h
  42. ├── elf.h
  43. ├── error.h
  44. ├── printfmt.c
  45. ├── stdarg.h
  46. ├── stdio.h
  47. ├── string.c
  48. ├── string.h
  49. └── x86.h
  50. ├── Makefile
  51. └── tools
  52. ├── function.mk
  53. ├── gdbinit
  54. ├── grade.sh
  55. ├── kernel.ld
  56. ├── sign.c
  57. └── vector.c
  58. 10 directories, 48 files

其中一些比较重要的文件说明如下:

bootloader部分

  • boot/bootasm.S :定义并实现了bootloader最先执行的函数start,此函数进行了一定的初始化,完成了从实模式到保护模式的转换,并调用bootmain.c中的bootmain函数。
  • boot/bootmain.c:定义并实现了bootmain函数实现了通过屏幕、串口和并口显示字符串。bootmain函数加载ucore操作系统到内存,然后跳转到ucore的入口处执行。
  • boot/asm.h:是bootasm.S汇编文件所需要的头文件,主要是一些与X86保护模式的段访问方式相关的宏定义。

ucore操作系统部分

系统初始化部分:

  • kern/init/init.c:ucore操作系统的初始化启动代码

内存管理部分:

  • kern/mm/memlayout.h:ucore操作系统有关段管理(段描述符编号、段号等)的一些宏定义
  • kern/mm/mmu.h:ucore操作系统有关X86 MMU等硬件相关的定义,包括EFLAGS寄存器中各位的含义,应用/系统段类型,中断门描述符定义,段描述符定义,任务状态段定义,NULL段声明的宏SEG_NULL, 特定段声明的宏SEG,设置中
    断门描述符的宏SETGATE(在练习6中会用到)
  • kern/mm/pmm.[ch]:设定了ucore操作系统在段机制中要用到的全局变量:任务状态段ts,全局描述符表 gdt[],加载全局描述符表寄存器的函数lgdt,临时的内核栈stack0;以及对全局描述符表和任务状态段的初始化函数gdt_init

外设驱动部分:

  • kern/driver/intr.[ch]:实现了通过设置CPU的eflags来屏蔽和使能中断的函数;
  • kern/driver/picirq.[ch]:实现了对中断控制器8259A的初始化和使能操作;
  • kern/driver/clock.[ch]:实现了对时钟控制器8253的初始化操作;- kern/driver/console.[ch]:实现了对串口和键盘的中断方式的处理操作;

中断处理部分:

  • kern/trap/vectors.S:包括256个中断服务例程的入口地址和第一步初步处理实现。注意,此文件是由tools/vector.c在编译ucore期间动态生成的;
  • kern/trap/trapentry.S:紧接着第一步初步处理后,进一步完成第二步初步处理;并且有恢复中断上下文的处理,即中断处理完毕后的返回准备工作;
  • kern/trap/trap.[ch]:紧接着第二步初步处理后,继续完成具体的各种中断处理操作;

内核调试部分:

  • kern/debug/kdebug.[ch]:提供源码和二进制对应关系的查询功能,用于显示调用栈关系。其中补全print_stackframe函数是需要完成的练习。其他实现部分不必深究。
  • kern/debug/kmonitor.[ch]:实现提供动态分析命令的kernel monitor,便于在ucore出现bug或问题后,能够进入kernel monitor中,查看当前调用关系。实现部分不必深究。
  • kern/debug/panic.c | assert.h:提供了panic函数和assert宏,便于在发现错误后,调用kernel monitor。大家可在编程实验中充分利用assert宏和panic函数,提高查找错误的效率。

公共库部分

  • libs/defs.h:包含一些无符号整型的缩写定义。
  • Libs/x86.h:一些用GNU C嵌入式汇编实现的C函数(由于使用了inline关键字,所以可以理解为宏)。

工具部分

  • Makefile和function.mk:指导make完成整个软件项目的编译,清除等工作。
  • sign.c:一个C语言小程序,是辅助工具,用于生成一个符合规范的硬盘主引导扇区。
  • tools/vector.c:生成vectors.S,此文件包含了中断向量处理的统一实现。

编译方法

首先下载lab1.tar.bz2,然后解压lab1.tar.bz2。在lab1目录下执行make,可以生成ucore.img(生成于bin目录下)。ucore.img是一个包含了bootloader或OS的硬盘镜像,通过执行如下命令可在硬件虚拟环境 qemu中运行bootloader或OS:

  1. $ make qemu

则可以得到如下显示界面(仅供参考)

  1. (THU.CST) os is loading ...
  2. Special kernel symbols:
  3. entry 0x00100000 (phys)
  4. etext 0x00103468 (phys)
  5. edata 0x0010ea18 (phys)
  6. end 0x0010fd80 (phys)
  7. Kernel executable memory footprint: 64KB
  8. ebp:0x00007b38 eip:0x00100a55 args:0x00010094 0x00010094 0x00007b68 0x00100084
  9. kern/debug/kdebug.c:305: print_stackframe+21
  10. ebp:0x00007b48 eip:0x00100d3a args:0x00000000 0x00000000 0x00000000 0x00007bb8
  11. kern/debug/kmonitor.c:125: mon_backtrace+10
  12. ebp:0x00007b68 eip:0x00100084 args:0x00000000 0x00007b90 0xffff0000 0x00007b94
  13. kern/init/init.c:48: grade_backtrace2+19
  14. ebp:0x00007b88 eip:0x001000a5 args:0x00000000 0xffff0000 0x00007bb4 0x00000029
  15. kern/init/init.c:53: grade_backtrace1+27
  16. ebp:0x00007ba8 eip:0x001000c1 args:0x00000000 0x00100000 0xffff0000 0x00100043
  17. kern/init/init.c:58: grade_backtrace0+19
  18. ebp:0x00007bc8 eip:0x001000e1 args:0x00000000 0x00000000 0x00000000 0x00103480
  19. kern/init/init.c:63: grade_backtrace+26
  20. ebp:0x00007be8 eip:0x00100050 args:0x00000000 0x00000000 0x00000000 0x00007c4f
  21. kern/init/init.c:28: kern_init+79
  22. ebp:0x00007bf8 eip:0x00007d61 args:0xc031fcfa 0xc08ed88e 0x64e4d08e 0xfa7502a8
  23. <unknow>: -- 0x00007d60 --
  24. ++ setup timer interrupts
  25. 0: @ring 0
  26. 0: cs = 8
  27. 0: ds = 10
  28. 0: es = 10
  29. 0: ss = 10
  30. +++ switch to user mode +++
  31. 1: @ring 3
  32. 1: cs = 1b
  33. 1: ds = 23
  34. 1: es = 23
  35. 1: ss = 23
  36. +++ switch to kernel mode +++
  37. 2: @ring 0
  38. 2: cs = 8
  39. 2: ds = 10
  40. 2: es = 10
  41. 2: ss = 10
  42. 100 ticks
  43. 100 ticks
  44. 100 ticks
  45. 100 ticks