1. 实验背景与目标解析
BUAA-OS-Lab0是北京航空航天大学操作系统课程的第一个实验环节,作为整个课程体系的入门项目,它承担着搭建实验环境、熟悉开发工具链的重要使命。这个实验看似基础,实则是后续所有操作系统实验的基石。我在实际完成过程中发现,很多同学在后续实验遇到的环境问题,80%都可以追溯到Lab0阶段的配置疏漏。
实验的核心目标是建立完整的操作系统开发环境,具体包括:
- 配置QEMU虚拟机作为实验平台
- 安装交叉编译工具链
- 验证最小可执行内核的编译与运行
- 熟悉GDB调试工具的基本用法
特别提醒:实验环境配置建议使用Ubuntu 20.04/22.04 LTS版本,这是经过验证最稳定的基础系统。其他发行版可能出现意料之外的兼容性问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实验环境搭建详解
2.1 基础软件包安装
首先需要安装必要的依赖库,这是后续所有操作的前提条件。执行以下命令:
bash复制sudo apt update
sudo apt install -y build-essential git qemu-system riscv64-unknown-elf-gcc \
gdb-multiarch python3 libsdl2-dev
这里有几个关键点需要注意:
riscv64-unknown-elf-gcc是RISC-V架构的交叉编译器,必须确保版本匹配gdb-multiarch支持多种架构调试,比单一架构的GDB更灵活- SDL2库是QEMU图形界面的依赖,缺少会导致虚拟机无法启动
2.2 QEMU配置与验证
QEMU版本选择至关重要,推荐使用6.2.0以上版本。验证QEMU是否正常工作:
bash复制qemu-system-riscv64 --version
qemu-system-riscv64 -machine virt -nographic -bios none
正常情况应该看到QEMU启动后停住并显示找不到可启动设备,这说明模拟器本身工作正常。如果遇到权限问题,需要将当前用户加入kvm组:
bash复制sudo usermod -aG kvm $(whoami)
newgrp kvm
3. 实验代码结构与编译
3.1 代码仓库获取
建议从课程官方仓库fork自己的副本:
bash复制git clone https://github.com/BienBoy/BUAA-OS-2023.git
cd BUAA-OS-2023/lab0
代码结构解析:
Makefile:核心编译控制文件kernel/:最小内核源代码tools/:辅助工具脚本gdbinit:GDB调试配置文件
3.2 编译过程解析
执行编译命令:
bash复制make all
这个简单的命令背后实际发生了这些关键步骤:
- 交叉编译器将汇编代码
entry.S转换为目标文件 - 编译C语言编写的内核初始化代码
- 链接器将所有目标文件合并为可执行镜像
- 生成包含调试信息的ELF文件
编译成功的标志是生成kernel.elf和kernel.bin两个文件。常见编译错误及解决方案:
| 错误类型 | 可能原因 | 解决方案 |
|---|---|---|
riscv64-unknown-elf-gcc: not found |
交叉编译器未安装 | 检查apt安装命令是否执行成功 |
undefined reference |
链接顺序错误 | 检查Makefile中的OBJS变量顺序 |
invalid option |
Makefile格式错误 | 确保使用tab而非空格缩进 |
4. 内核运行与调试实战
4.1 QEMU启动内核
使用以下命令启动编译好的内核:
bash复制make run
这个命令实际执行的是:
bash复制qemu-system-riscv64 -machine virt -bios none -kernel kernel.bin \
-nographic -serial mon:stdio
关键参数说明:
-machine virt:指定模拟的硬件平台-bios none:不使用BIOS直接启动内核-nographic:禁用图形界面,纯命令行模式-serial mon:stdio:将串口输出重定向到终端
正常启动后应该看到内核输出的"Hello OS!"信息,然后进入无限循环。如果没有输出,可能是:
- 串口配置错误
- 内核入口函数未正确执行
- 编译生成的二进制文件损坏
4.2 GDB调试技巧
调试是操作系统开发的核心技能,Lab0要求掌握基本的GDB用法。调试会话启动:
bash复制make debug
这会启动QEMU的GDB stub并自动加载调试配置。几个实用调试命令:
- 设置断点:
gdb复制b *0x80000000 # 在内核入口处断点
b kernel_main # 在C函数入口断点
- 单步执行:
gdb复制si # 汇编级单步
n # 源码级单步
- 查看寄存器:
gdb复制info registers
x/10i $pc # 反汇编当前指令
调试技巧:在
gdbinit中添加set disassemble-next-line on可以自动显示下条指令的汇编代码,对理解执行流程非常有帮助。
5. 实验报告撰写要点
实验报告是课程考核的重要组成部分,好的报告应该包含:
5.1 必写内容
-
环境配置过程记录
- 详细记录所有安装的软件包及版本
- 遇到的错误及解决方法
-
代码流程分析
- 从
entry.S到kernel_main()的执行路径 - 关键汇编指令的作用解析
- 从
-
调试过程记录
- 设置的断点位置及原因
- 观察到的寄存器/内存变化
5.2 加分项建议
-
Makefile解析
- 分析编译系统的组织方式
- 解释关键编译选项的作用
-
扩展实验
- 修改输出信息验证理解
- 尝试添加简单的函数调用
-
性能分析
- 测量内核启动时间
- 分析影响启动速度的因素
6. 常见问题解决方案
根据往届学生的实践经验,我整理了这些高频问题及解决方案:
-
QEMU无法启动
- 现象:卡在
Waiting for gdb connection... - 检查:
ps aux | grep qemu确认进程是否存在 - 解决:重启QEMU并检查端口冲突
- 现象:卡在
-
GDB连接失败
- 现象:
Connection timed out - 检查:确保QEMU的
-gdb tcp::1234参数正确 - 解决:尝试更换端口号如
1235
- 现象:
-
交叉编译器报错
- 现象:
unrecognized opcode - 检查:
riscv64-unknown-elf-objdump -d kernel.elf - 解决:确认编译目标架构是否正确
- 现象:
-
串口无输出
- 现象:QEMU启动但无任何输出
- 检查:确认
puts()函数是否被正确调用 - 解决:在汇编入口添加简单输出测试
7. 进阶学习建议
完成基础实验后,如果想深入理解底层机制,可以尝试:
- 修改链接脚本
kernel.lds,观察对内存布局的影响 - 在汇编层面添加新的函数调用,理解ABI规范
- 使用
objdump工具分析生成的可执行文件结构 - 对比不同优化等级(-O0/-O2)生成的汇编代码差异
我在实验过程中发现,认真完成这些扩展练习的同学,在后续的Lab1-Lab6中明显表现出更强的调试能力和系统理解深度。特别是对ELF文件格式的理解,在实现进程管理时会事半功倍。
