操作系统实验Ucore lab1

本文是中山大学数据科学与计算机学院的操作系统实验报告,关注Ucore Lab1,涉及系统软件启动过程。实验包括理解make生成执行文件、使用qemu执行调试、分析bootloader进入保护模式和加载ELF过程、实现堆栈跟踪函数以及中断初始化和处理。通过实验,深入理解分段存储管理、设备管理、启动流程、中断处理等核心概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

lab1

前言

这是中山大学数据科学与计算机学院2019年操作系统实验中关于Ucore的项目以及实验报告,实验要求与Ucore手则有少量出入。
所有源代码已经上传至github。
github个人主页: https://starashzero.github.io
项目地址: https://github.com/StarashZero/Ucore-homework

【实验题目】系统软件启动过程

【实验目的】

操作系统是一个软件,也需要通过某种机制加载并运行它。在这里我们将通过另外一个更加简单的软件-bootloader 来完成这些工作。为此,我们需要完成一个能够切换到x86 的保护模式并显示字符的bootloader,为启动操作系统ucore 做准备。lab1 提供了一个非常小的bootloader 和ucoreOS,整个bootloader 执行代码小于512 个字节,这样才能放到硬盘的主引导扇区中。通过分析和实现这个bootloader 和ucore OS,读者可以了解到:
● 基于分段机制的存储管理
● 设备管理的基本概念
● PC 启动bootloader 的过程
● bootloader 的文件组成
● 编译运行 bootloader 的过程
● 调试 bootloader 的方法
● ucore OS 的启动过程
● 在汇编级了解栈的结构和处理过程
● 中断处理机制
● 通过串口/并口/CGA 输出字符的方法

【实验方案】

包括:硬件或虚拟机配置方法、软件工具与作用、方案的思想、相关原理、程序流程、算法和数据结构、程序关键模块,结合代码与程序中的位置位置进行解释,组员工作分工。
虚拟机使用Ubuntu,主要的代码编辑与查看工具VSCode,结合Ucore启动过程指导与网上的资料完成实验。

练习 1:理解通过make 生成执行文件的过程。(要求在报告中写出对下述问题的回答)

在此练习中,大家需要通过静态分析代码来了解:

  1. 操作系统镜像文件 ucore.img 是如何一步一步生成的?(需要比较详细地解释Makefile 中每一条相关命令和命令参数的含义,以及说明命令导致的结果)
    首先找到创建ucore.img的makefile代码如下
# create ucore.img
UCOREIMG	:= $(call totarget,ucore.img)

$(UCOREIMG): $(kernel) $(bootblock)
	$(V)dd if=/dev/zero of=$@ count=10000
	$(V)dd if=$(bootblock) of=$@ conv=notrunc
	$(V)dd if=$(kernel) of=$@ seek=1 conv=notrunc

$(call create_target,ucore.img)

可以看到要生成ucore.img首先要生成kernel和bootblock
生成kernel代码如下

# create kernel target
kernel = $(call totarget,kernel)

$(kernel): tools/kernel.ld

$(kernel): $(KOBJS)
	@echo + ld $@
	$(V)$(LD) $(LDFLAGS) -T tools/kernel.ld -o $@ $(KOBJS)
	@$(OBJDUMP) -S $@ > $(call asmfile,kernel)
	@$(OBJDUMP) -t $@ | $(SED) '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $(call symfile,kernel)

$(call create_target,kernel)

运行makefile,在其中找到kernel的实际命令为
在这里插入图片描述
关键参数
-m 模拟指定的连接器
-nostdlib 不使用标准库
-T 指定命令文件
-o 指定输出文件的名称
可以发现生成kernel所需要的文件有:tools/kernel.ld obj/kern/init/init.o obj/kern/libs/readline.o obj/kern/libs/stdio.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/debug/panic.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/intr.o obj/kern/driver/picirq.o obj/kern/trap/trap.o obj/kern/trap/trapentry.o obj/kern/trap/vectors.o obj/kern/mm/pmm.o obj/libs/printfmt.o obj/libs/string.o
生成这些文件的makefile为下面的批处理代码

# kernel

KINCLUDE	+= kern/debug/ \
			   kern/driver/ \
			   kern/trap/ \
			   kern/mm/

KSRCDIR		+= kern/init \
			   kern/libs \
			   kern/debug \
			   kern/driver \
			   kern/trap \
			   kern/mm

KCFLAGS		+= $(addprefix -I,$(KINCLUDE))

$(call add_files_cc,$(call listf_cc,$(KSRCDIR)),kernel,$(KCFLAGS))

其实际代码为(以init.o为例)
在这里插入图片描述
关键参数
-fno-bultin 除非用_builtin_前缀,否则不进行builtin函数的优化
-ggdb 此选项将尽可能的生成gdb的可以使用的调试信息
-m32 生成适用于32位环境的代码
-gstabs 此选项以stabs格式声称调试信息,但是不包括gdb调试信息
-nostdinc 使编译器不在系统缺省的头文件目录里面找头文件
-fno-stack-protector不生成用于检测缓冲区溢出的代码
-I<dir> 添加搜索头文件的路径
kernel生成完成

生成blootblock的makefile代码如下

# create bootblock
bootfiles = $(call listf_cc,boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

bootblock = $(call totarget,bootblock)

$(bootblock): $(call toobj,$(bootfiles)) | $(call totarget,sign)
	@echo + ld $@
	$(V)$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 $^ -o $(call toobj,bootblock)
	@$(OBJDUMP) -S $(call objfile,bootblock) > $(call asmfile,bootblock)
	@$(OBJCOPY) -S -O binary $(call objfile,bootblock) $(call outfile,bootblock)
	@$(call totarget,sign) $(call outfile,bootblock) $(bootblock)

$(call create_target,bootblock)

其生成代码为
在这里插入图片描述
关键参数:
-N设置代码段和数据段均可读写
可以看到生成bootblock需要bootasm.o,bootmain.o,以及sign
bootasm.o和bootmain.o由以下makefile代码生成

bootfiles = $(call listf_cc,boot)
$(foreach f,$(bootfiles),$(call cc_compile,$(f),$(CC),$(CFLAGS) -Os -nostdinc))

实际代码为
在这里插入图片描述
sign的makefile代码为

# create 'sign' tools
$(call add_files_host,tools/sign.c,sign,sign)
$(call create_target_host,sign,sign) 

生成代码为
在这里插入图片描述
2. 一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?

    char buf[512];
    memset(buf, 0, sizeof(buf));
    FILE *ifp = fopen(argv[1], "rb");
    int size = fread(buf, 1, st.st_size, ifp);
    if (size != st.st_size) {
   
   
        fprintf(stderr, "read '%s' error, size is %d.\n", argv[1], size);
        return -1;
    }
    fclose(ifp);
    buf[510] = 0x55;
    buf[511] = 0xAA;

一个磁盘主引导扇区512字节,且第510个字节为0X55,第511个字节为0XAA

练习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值