北航操作系统课程-第三次作业-系统引导与程序装载

北航操作系统课程-第三次作业-系统引导与程序装载


北京航空航天大学计算机学院-2020春操作系统课程
题目作者为北航计算机学院操作系统课程组,答案为博主原创。水平有限,无法保证作答正确性,如有错误敬请批评指正。部分作答源自百度谷歌等其他资料,如有侵权联系删除


1 假设有一个简单的计算机硬件系统,CPU 是同学们自己设计的,有内存和硬盘(可以没有MMU),请设计一个尽量简单的启动过程。(要求:列出必要的硬件支持、启动软件的基本功能和启动过程,只要将控制权交给操作系统镜像就算完成启动)

首先假设我们同学自己设计的简单硬件系统如下:

  • MIPS体系结构的CPU
  • Bootloader存放在flash上
  • 没有MMU作地址转换,没有cache和多级存储
  • 内存分区简单划分为内核区和用户区
  • 有外设总线可以用于连接少部分外设

在此基础上讨论其启动过程。系统的启动过程大致如下所述:

  1. 系统加电,开始运行flash上的汇编代码,包括初始化向量表、协处理器;设置CPU、总线和内存的工作频率;设置堆栈等。最终跳转至C语言入口,开始执行flash上的C代码。
  2. 利用C语言做一些更多设备和软件的初始化,包括时钟、环境变量、串口、控制台的初始化,显示一些Bootloader的启动信息,初始化整个内存。至此,串口和内存完成了启动。
  3. 将内存划分为用户和内核区,设置内核堆栈,然后将flash上的代码搬到内存RAM上继续运行,在此步骤也完成flash和RAM地址转换重定位。
  4. 初始化malloc、外设总线及所连接的外设,将硬盘上的操作系统镜像拷贝到内存的内核区(操作系统第一条指令所在的物理地址处),将控制权交给操作系统。

2 编写一段程序,分别输出属于该程序代码段、数据段、堆和栈的地址。(提示:不要求一定要输出各个段的首地址,不要编一个ELF 解析程序,只要输出不同类型变量的地址就可以。)

在Linux环境下,可执行文件(ELF文件)在没有调入内存执行时拥有3个部分,分别是text、data和BSS段,而堆栈段是在程序装入内存后由系统分配的。在C语言中,各个段的内容如下:

段名内容
Text segment可执行代码、常量数据
Data segment已初始化的全局变量、已初始化的全局静态变量、局部静态变量
BSS segment未初始化的全局变量
Heap动态内存分配
Stack局部变量、函数参数

其中常量之所以归入了Text段,依我个人见解,有可能是在编译过程中常量优化将其直接装载进代码中。根据C语言的特性,我们可以编写如下的代码,通过不同类型的变量来输出不同段的地址:

/*
 * @Name: 03-02.c
 * @Description: Operating System course by SCSE of Beihang University.
 * @Description: To show the address of each segment when running C program on Linux(Ubuntu16.04).
 * @Version: 1.0
 * @Author: JeremyZhao1998
 * @Date: 2020-03-11 16:28:09
 * @LastEditors: JeremyZhao1998
 * @LastEditTime: 2020-03-11 18:59:18
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Text segment: code, constants
void code(){}
const char constants[] = "constants";

// Data segment: initialized global variables
char initialized_global[] = "initialized_global";
static char initialized_global_static[] = "initialized_global_static";

// Bss segment: uninitialized global variables
char uninitialized_global[20];

int main()
{
	strcpy(uninitialized_global, "uninitialized_global");
	
	// Data segment: local static variables
	static char local_static[] = "local_static";

	// Heap: dynamic memory allocation
	char* dynamic_memory_allocation;
	dynamic_memory_allocation = (char*)malloc(sizeof(char)*10);

	// Stack: local variables
	char local[] = "local";

	printf("\n===================================================================\n\n");

	printf("Text segment: code, constants\n");
	printf("Function address:                           %p\n", &code);
	printf("Constant address:                           %p\n", &constants);
	printf("-------------------------------------------------------------------\n");
	printf("Data segment: initialized global variables\n");
	printf("Initialized global variable address:        %p\n", &initialized_global);
	printf("Initialized static global variable address: %p\n", &initialized_global_static);
	printf("Local static variable address:              %p\n", &local_static);
	printf("-------------------------------------------------------------------\n");
	printf("Bss segment: uninitialized global variables\n");
	printf("Uninitialized global variable address:      %p\n", &uninitialized_global);
	printf("-------------------------------------------------------------------\n");
	printf("Heap: dynamic memory allocations\n");
	printf("Dynamic memory allocation pointer address:  %p\n", dynamic_memory_allocation);
	printf("-------------------------------------------------------------------\n");
	printf("Stack: local variables\n");
	printf("Local variable address:                     %p\n", &local);

	printf("\n===================================================================\n\n");

	return 0; 
}

其中代码的解释如注释,不再赘述。上面的代码运行在Linux环境下(Ubuntu16.04),其运行结果如下图:
在这里插入图片描述
可以看出,常量确实和函数一起并入Text段,而Text、Data、BSS和堆依次在低地址空间向上延伸,栈空间从高地址向下延伸,与本次作业第四题Linux进程的内存分布相符。

我们可以通过objdump命令来查看可执行文件各个段的大小内容等信息。下图分别是.o文件和最终.out文件dump出的信息:
在这里插入图片描述在这里插入图片描述
其中,Size一列是各个段的大小,File off一列是该段的起始地址,每个段的第二行显示了一些段的信息。可以看到链接重定位前后各个段的大小和起始地址都是有差异的,而通过.out文件右起第二列的相对起始地址也可以看出,各个段在可执行文件中和运行在内存时的相对地址也基本是吻合的。

参考博客:https://blog.csdn.net/yangcunbiao/article/details/83020443


3 举例说明,ELF格式的程序在重定位时对函数和全局变量的不同计算方法。

以课堂讲授的32位MIPS体系结构为例,在MIPS中,不同的重定位类型有着不同的重定位地址计算方法,如下图:
在这里插入图片描述
其中A和AHL分别是指令和地址的附加值,主要用于解决MIPS中少量的变长指令或没有对齐的地址的问题;R_MIPS_26中Local指的是部分带有特殊局部标记的符号,External指的是全局或外部符号;R_MIPS_HI16和R_MIPS_LO16是将32位数据的高16位与低16位分开进行重定位。以具体的例子来看,下图是一段C代码编译过后的.out文件,通过反汇编和ReadELF工具dump出的符号表:
在这里插入图片描述
符号表中符号名称可以看出其类型,read_something是全局函数,而some_global_variable是全局变量。可以从该符号表中看出,函数的重定位类型是R_MIPS_26,其重定位计算方法是处理对齐后右移两位;全局变脸的重定位被拆分为高16位和低16位,其计算方法分别是取高16位和取低16位后处理地址对齐。


4 描述Linux系统中一个可执行文件加载到内存后地址空间的布局,包括代码段、数据段、堆和栈等。(用图和文字描述)

在Linux中,每一个进程都被抽象为task_struct结构体,称为进程描述符,存储着进程各方面的信息,例如打开的文件,信号以及内存等等。task_struct的一个属性mm_struct管理着进程的所有虚拟内存,称为内存描述符。在mm_struct结构体中,存储着进程各个内存段的开始以及结尾,如下图:
在这里插入图片描述
可以看出,进程装载进内存后,从低地址到高地址依次排布着Text段、Data段、BSS段,随后是动态分配的堆、内存映射段以及从高地址向低地址延申的栈。

参考博客:https://www.linuxprobe.com/linux-memory-layout.html

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《项目介绍》 操作系统原理作业-支持多进程并发的操作系统源码+项目说明.zip 文件结构: src文件夹中包含4个文件夹、1个.asm文件。 1. img文件夹中包含了本次实验的1个映像文件XOS5.0,XOS5.0是本次实验的最终完成品。 2. kernel文件夹中包含了本次实验的2个源代码文件,其中操作系统内核源代码文件kernel.asm和ckernel.c。 3. user program文件夹中包含了6个用户程序源代码。 4. obj file文件夹中包含了2个.o文件,.o文件是内核编译出来的二进制文件。 5. 另外还有引导扇区程序源代码boot.asm 实验环境: 编译操作系统:Ubuntu 18.04 LTS , C 语言编译器:gcc 7.4.0-1 ubuntu2.3;汇编语言编译器:nasm 2.13.02-0.1, 链接器:ld , 虚拟机软件:VMware Workstation 15 。 【注】 1.项目代码均经过功能验证ok,确保稳定可靠运行。欢迎下载使用体验! 2.主要针对各个计算机相关专业,包括计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师、企业员工。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈!
【资源说明】 1.项目代码均经过功能验证ok,确保稳定可靠运行。欢迎下载食用体验! 2.主要针对各个计算机相关专业,包括计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师、企业员工。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【项目介绍】 C++课程作业-基于Qt实现的链表操作演示系统源码(含详细注释+报告).zip 1.1 题目 分别以单链表、循环链表、双向链表为例,实现线性表的建立、插入、删除、查找等基 本操作。 要求:能够把建立、插入、删除等基本操作的过程随时显示输出来。 1.2 软件功能 对于单链表、循环链表和双向链表,均能实现以下功能: (1)线性表的建立,建立一个带头结点的空链表; (2)线性表插入操作,输入插入索引与插入元素值,将元素插入到链表指定位置; (3)线性表删除操作,输入删除元素的索引,删除该位置的元素; (4)线性表查找操作,输入要查找的元素值,返回第一个等于该值得元素索引; (5)线性表修改操作,输入要修改的索引与修改后的值,修改线性表对应元素; (6)能够对各种特殊情况如索引不合法等进行判断并给出提示。 1.3 设计思想 根据题意,需要对不同链表进行同样的几项基本操作,实现标准交互式图形界面,可以 分为算法设计和界面设计两部分。 算法设计方面:对于单链表,本程序链表的建立采用带头结点方式,即每次建立链表都 动态申请一个头结点,头结点的后继是 NULL;链表的插入操作需要从头遍历链表,在指定 索引处修改插入位置前驱结点的 next 指针指向新结点,新结点的 next 指针则指向该位置原 结点;链表的删除操作同样需要从头遍历链表,将指定索引处结点的前驱结点的 next 指针 修改为指向该结点的后继结点,并删除当前结点即可;链表的查找操作需要从头遍历链表比 较当前访问元素与要查找元素是否相等,若相等则返回索引,若访问完整个链表都找不到相 同的元素,则提示查找失败;链表修改操作无需改变链表长度,从头遍历链表找到对应位置 元素修改其值即可。循环链表和双向链表的相关操作基本同单链表,不同的是循环链表最后 一个结点的 next 指针指向头结点,双向链表除了指向元素后继的 next 指针还有指向元素前 驱的 prior 指针。三种链表的实现有所不同,但对于本程序的场景体现不出三种链表的差异。 界面设计方面:可以利用 QT 框架添加按钮、选择框、文本展示框等控件,将三种链表 的五项基本操作整合到一个界面中。
【资源介绍】 课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip课程作业-基于C++实现的简单医疗预约系统源码.zip 课程作业-基于C++实现的简单医疗预约系统源码.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,也适用于小白学习入门进阶。当然也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或者热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载,沟通交流,互相学习,共同进步!
北航操作系统课程设计的Lab0旨在帮助学生熟悉实际的操作系统开发环境和相关工具的使用。在这个实验中,我们首先需要安装Linux操作系统并进行相关配置,以便进行后续的实验操作。 在Lab0中,我们需要安装和配置虚拟机软件,如VirtualBox或VMware,以创建一个类似操作系统的虚拟环境。然后,我们需要从北航操作系统课程设计网站下载并安装提供的操作系统实验环境,如ucore OS等。 安装完成后,我们需要熟悉Linux系统的基本命令,并了解与操作系统开发相关的编译工具链,如gcc和make。这些工具在操作系统的编译和运行过程中起着至关重要的作用。我们将学习如何使用gcc编译C语言程序,并使用make工具自动化编译过程。 在实验中,我们还将学习如何通过交叉编译和链接,将编译生成的操作系统镜像加载到虚拟机中并运行。我们将通过VirtualBox或VMware的网络设置,将虚拟机与宿主机连接起来,以便进行操作系统的调试和测试。 通过完成Lab0,我们将能够顺利地进行后续的操作系统实验,掌握操作系统开发的基本技能和工具。我们将能够编写C语言的系统代码,实现操作系统的基本功能和特性。此外,我们还将学习到操作系统的底层原理和相关的调试技巧。 总而言之,北航操作系统课程设计的Lab0是一个重要的起点,它帮助我们搭建实验环境、熟悉操作系统开发工具和命令,并为后续的实验打下坚实的基础。通过此实验,我们将能够更深入地理解操作系统的工作原理,并为我们未来的学习和研究提供良好的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值