项目组成和执行流
lab0的项目组成如下:
内核启动
kern/init/entry.S
: OpenSBI启动之后将要跳转到的一段汇编代码。在这里进行内核栈的分配,然后转入C语言编写的内核初始化函数。
kern/init/init.c
: C语言编写的内核入口点。主要包含kern_init()
函数,从kern/entry.S
跳转过来完成其他初始化工作。
设备驱动
kern/driver/console.c(h)
: 在QEMU上模拟的时候,唯一的“设备”是虚拟的控制台,通过OpenSBI接口使用。简单封装了OpenSBI的字符读写接口,向上提供给输入输出库。
库文件
libs/riscv.h
: 以宏的方式,定义了riscv指令集的寄存器和指令。如果在C语言里使用riscv指令,需要通过内联汇编和寄存器的编号。这个头文件把寄存器编号和内联汇编都封装成宏,使得我们可以用类似函数的方式在C语言里执行一句riscv指令。
libs/sbi.c(h)
: 封装OpenSBI接口为函数。如果想在C语言里使用OpenSBI提供的接口,需要使用内联汇编。这个头文件把OpenSBI的内联汇编调用封装为函数。
libs/defs.h
: 定义了一些常用的类型和宏。 例如bool 类型(C语言不自带,这里typedef int bool
)。
libs/string.c(h)
: 一些对字符数组进行操作的函数,如memset(),memcpy()
等,类似C语言的string.h
。
kern/libs/stdio.c
, libs/readline.c
, libs/printfmt.c
: 实现了一套标准输入输出,功能类似于C语言的printf()
和getchar()
。需要内核为输入输出函数提供两个桩函数(stub): 输出一个字符的函数,输入一个字符的函数。在这里,是cons_getc()
和cons_putc()
。
kern/errors.h
: 定义了一些内核错误类型的宏。
编译、链接脚本
tools/kernel.ld
: ucore的链接脚本(link script), 告诉链接器如何将目标文件的section组合为可执行文件。
tools/function.mk
: 定义Makefile中使用的一些函数
Makefile
: GNU make编译脚本
执行流
最小可执行内核的执行流为:
加电 -> OpenSBI启动 -> 跳转到 0x80200000 (kern/init/entry.S
)->进入kern_init()
函数(kern/init/init.c
) ->调用cprintf()
输出一行信息->结束
cprintf()
函数的执行流为:
接受一个格式化字符串和若干个需要输出的变量作为参数 -> 解析格式化的字符串,把需要输出的各种变量转化为一串字符 -> 调用console.c
提供的字符输出接口依次输出所有字符(实际上console.c
又封装了sbi.c
向上提供的OpenSBI接口)
最后更新于