《计算机操作系统实验》
目录
问题2:启动带调试的 QEMU,使用 GDB 的where命令来跟踪入口(第一个函数)及 bootloader 的地址。(20分)
问题3:查看build/kernel.img的objdump信息。比较每一个段中的 VMA 和LMA 是否相同,为什么?(20分)
问题4:编辑请简单解释,在哪个文件或代码段中指定了 ChCore 物理内存布局。(20分)
问题5:启动ChCore中的第一个用户态进程、线程。(20分)
参考:ChCore Lab1 机器启动 实验笔记 - 康宇PL - 博客园 (cnblogs.com)
问题1:编译和运行ChCore。(20分)
实验环境基于Ubuntu:
- 在Ubuntu 终端安装软件:
- 安装docker
- 安装git环境:sudo apt-get install git
- 编译lab时运行:/scripts/build.sh
编译和运行ChCore
make build:
make qemu:
问题2:启动带调试的 QEMU,使用 GDB 的where命令来跟踪入口(第一个函数)及 bootloader 的地址。(20分)
按照实验说明使用GDB来远程调试chcore以及查看其入口地址为_start,其物理地址为0x80000处。我们查看其代码位于start.S,然后查看其cmakelist以及linker-aarch64.lds.in的文件发现其位于.init节。
start.S/文件:
cmakelist文件:
linker-aarch64.lds.in 文件:
那么我们来readelf来查看是否.init节的起始地址时0x80000,结果还真是,这样就跟gdb的where查看的地址一模一样对应上了。
问题3:查看build/kernel.img的objdump信息。比较每一个段中的 VMA 和LMA 是否相同,为什么?(20分)
chcore是qemu模拟Raspi3从SD卡加载.img镜像,我们来看器ld脚本规则,可以发现为何不同了,对于.init节并没有做任何处理,直接加载执行,其他的几个段都紧挨着.init节后面(紧凑节约空间,毕竟bss也不占空间,无法直接在LMA展开),然后加载到LMA然后展开运行。通过分析可知 init 段没有单独指定 VMA 和 LMA,所以它俩的地址都是 0x80000,而 text 段开始分别指定了 VMA 和 LMA,它俩就不同了。
问题4:请简单解释,在哪个文件或代码段中指定了 ChCore 物理内存布局。(20分)
- bootloader:Lab 1 里我们可以知道 img_start 和 init_start 都被硬编码为了 0x80000,分别代表 chcore 镜像的开始地址和 bootloader 的开始地址。整个 .init 段就是 bootloader 所有代码和全局变量的内存空间。至于 booloader 里的临时变量,我们在汇编课里学过临时变量优先放在寄存器里,其次选择放在函数栈里。放在寄存器里的不占内存;放在函数栈的,因为 bootloader 的函数栈就是一个全局数组,所以本质上还是放在全局变量里。
- KERNEL IMG:这一块就是内核所有代码和全局变量的空间。链接脚本里指明了 .init 段之后就是内核的 .text、 .rodata、 .bss 等等的程序段。这些段的末尾就是镜像的末尾 img_end。为什么内核分这么多个段而 bootloader 只有一个段呢?因为 Lab 1 我们发现 CMakeLists.txt 中将 bootloader 所有的目标文件打包成了一个 init_object 的整体然后放在了 .init 段里。
- reserved:bootloader 是从 0x00080000 之后放的。从 0x00000000 到 0x00080000 就是保留的区域,不使用。它的作用需要学完虚拟内存整章才能明白:把开头留出来是为了在方便在访问空指针时报段错误。因为这一段没有做任何映射,所以访问必引发异常。
问题5:启动ChCore中的第一个用户态进程、线程。(20分)
ChCore中的进程-线程的组织方式是:一个进程可以创建多个线程。
那么首先我们需要创建进程。
创建进程的实现在process中实现,由于ChCore基于Capability-object的组织方式,所以创建进程的过程大概可以进行划分:
- 创建type为process的实体(object),并做初始化。
- 初始化进程的capability。
- 创建type为vmspace的实体,并做初始化。
- 进程的capability增加vmspace
在 kernel/process/process.c 文件下
创建线程:
进程创建完成后,紧接着创建它的第一个线程。创建主线程的函数是thread_create_main。
首先根据代码来归纳一下它的任务:
- 创建type为PMO的实体用作线程栈,并初始化。
- 进程的capability增加上面创建的堆栈
- 配置堆栈属于用户进程内存空间
- 加载hello.bin
- 创建thread实体并初始化
- 进程的capability增加thread实体
在kernel/process/thread.c 文件下:
在 kernel/sched/sche.c 文件下:
在 kernel/sched/context.c 文件下:
创建进程与线程