ucore step by step
tutorial
tutorial
  • 欢迎来到ucore step-by-step的世界
  • lab0: 预备起
    • 溯源: ucore的历史
    • 概览: 指导书的结构
    • 开搞: 实验环境搭建
  • lab0.5: 比麻雀更小的麻雀(最小可执行内核)
    • 内存布局,OpenSBI,elf和bin
    • 链接脚本和入口点
    • "真正的"入口点
    • 从SBI到stdio
    • Just make it
    • 项目组成和执行流
  • lab1: 断, 都可以断
    • 掉进兔子洞(中断入口点)
    • 中断处理程序
    • 滴答滴答(时钟中断)
    • 项目组成和执行流
  • lab2: 物理内存和页表
    • 内核初始映射
    • 物理内存管理
    • 页面分配算法
    • 项目组成和执行流
  • lab3: 缺页异常和页面置换
    • 扫清外围
    • 使用多级页表
    • 页面置换机制
    • FIFO置换算法
    • 项目组成和执行流
  • lab4: 进程管理
    • 进程与线程
    • 相关数据结构
    • 进程模块初始化
    • 进程切换
    • 项目组成和执行流
  • lab5: 用户程序
    • 用户程序
    • system call!
    • 中断处理
    • 项目组成和执行流
  • lab6: 进程调度
    • 再次认识进程切换
    • 调度算法框架
    • 项目组成和执行流
  • lab7: 同步互斥
    • 同步互斥的基本概念
    • 信号量
    • 条件变量与管程
    • 项目组成和执行流
  • lab8: 文件系统
    • 文件系统抽象层VFS
    • 硬盘文件系统SFS
    • 设备即文件
    • 从zhong duan 到 zhong duan
    • 项目组成和执行流
  • 练习题
    • lab1
    • lab2
    • lab3
    • lab4
    • lab5
    • lab6
    • lab7
    • lab8
  • 附录
    • makefile
由 GitBook 提供支持
在本页
  • 内核启动
  • 设备驱动
  • 编译、链接脚本
  • 执行流

这有帮助吗?

  1. lab0.5: 比麻雀更小的麻雀(最小可执行内核)

项目组成和执行流

lab0的项目组成如下:

── Makefile 
├── kern
│   ├── debug
│   │   ├── assert.h
│   │   ├── kdebug.c
│   │   ├── kdebug.h
│   │   ├── kmonitor.c
│   │   ├── kmonitor.h
│   │   ├── panic.c
│   │   └── stab.h
│   ├── driver
│   │   ├── clock.c
│   │   ├── clock.h
│   │   ├── console.c
│   │   ├── console.h
│   │   ├── intr.c
│   │   ├── intr.h
│   │   ├── kbdreg.h
│   │   ├── picirq.c
│   │   └── picirq.h
│   ├── init
│   │   ├── entry.S
│   │   └── init.c
│   ├── libs
│   │   ├── readline.c
│   │   └── stdio.c
│   ├── mm
│   │   ├── memlayout.h
│   │   ├── mmu.h
│   │   ├── pmm.c
│   │   └── pmm.h
│   └── trap
│       ├── trap.c
│       ├── trap.h
│       └── trapentry.S
├── libs
│   ├── defs.h
│   ├── elf.h
│   ├── error.h
│   ├── printfmt.c
│   ├── riscv.h
│   ├── sbi.c
│   ├── sbi.h
│   ├── stdarg.h
│   ├── stdio.h
│   ├── string.c
│   └── string.h
└── tools
    ├── function.mk
    ├── kernel.ld

内核启动

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接口)

上一页Just make it下一页lab1: 断, 都可以断

最后更新于4年前

这有帮助吗?