操作系统——内核雏形

实验目的:

如何生成一个内核,能引导该内核,并进行扩展

实验内容:

  1. 汇编和C的互相调用方法
  2. ELF文件格式
  3. 使用Loader加载ELF文件
  4. 如何加载并扩展内核
  5. 设计题:修改启动代码,在引导过程中在屏幕上画出一个你喜欢的ASCII图案,并将第三章的内存管理功能代码、你自己设计的中断代码集成到你的kernel文件目录管理中,并建立makefile文件,编译成内核,并引导

实验环境:

VMware+Ubuntu32位

实验步骤:

1.汇编和C的互相调用方法


调用关系示意图如上,我们来看一下代码。


将foo.asm中定义的函数设为global模式,使得可以被调用,同时导入choose函数 int choose(int a ,int b)。

在bar.c中调用myprint函数,并定义choose函数。
编译,链接,运行:

可以发现调用是成功的!

2.ELF文件格式


格式图如上所示,其中我们来分别分析每一个部分的含义和数据结构。
ELF header:

Program header:

Program header描述的是一个段在文件中的位置、大小以及它被放进内存后所在的位置和大
小。如果我们想把一个文件加载进内存的话,需要的正是这些信息。

3.使用Loader加载ELF文件

我们的期望是使用Loader加载ELF文件,在之后肯定是要加载内核文件的。加载一个文件无非就是寻找文件、定位文件、读入内存三个步骤,所以在这次的loader中也是遵循这个步骤。

和之前实验的思路是类似的,只不过我们这次寻找的是kernel.bin文件。
在这里我们先随便写一个简单的kernel.asm文件来测试一下:

就是,现实一个字母K罢了。
我们来跑一跑这个loader程序


可以看见是成功的,因为出现了ready. 字符

4.如何加载并扩展内核

在上一步骤中,我们已经把kernel加载进了内存,但要想使内核运行并移交控制权,我们还需要先进入保护模式。
进入保护模式的代码已经很常见了,如下所示:

但与之前不一样的是,之前大多数描述符的段基址都是运行时计算后填入相应位置的,此时我们不需要这样了,因为我们自己加载了loader,已经确定了段地址并定义为了BaseOfLoader,所以在Loader中出现的变量的物理地址可以由下公式计算:
标号物理地址 = BaseOfLoader * 10h + 标号的偏移
于是我们将BaseOfLoader定义在一个文件里:

我们直接用了一个宏BaseOfLoaderPhyAddr来表示BaseOfLoader * 10h,当然是为了方便啦。
保护模式的代码如下,仅仅只是打印一个字符P

运行一下:

看到P,证明跳入保护模式成功。
成功跳入保护模式之后,我们获得内存信息、开启分页操作、最终整理内核并移交控制权。
获得内存信息是我们之前实验的内容,我们使用15h中断来完成,代码如下:

当然我们不能比之前的实验差,所以我们也把他加载进显存并打印:

和之前的代码基本就是从第三章中拿来直接使用的,别忘了将调用的函数DispInt,DispStr等包含在32位代码段中。
得到内存信息后,启动分页。

运行:

在之前的基础上出现了第三章那样的内存信息。
内存信息获取成功,分页开启成功,接下来我们将内存中的kernel程序整理,并移交控制权。
别忘了,我们的内核程序是一个elf程序,elf程序的program header table字段是有重要含义的,让我再来复习一下。



之前说到,我们要整理kernel程序,也就是说我们要把之前导入内存的代码整理到一个指定位置,这里我们需要使用memcpy函数。

具体实现如下:

但是,由于ld生成的可执行文件中p_vaddr的值较大,在这里超过我们的内存范围,所以我们需要修改一下ld指令时的参数。

解决了内存的问题之后,我们就可以向内核交出控制权了。

运行一下试试:

可以看到,出现了K字符。证明此时内核成功运行了!
接下来我们来进行内核扩展,先跑一下代码看看结果:

可以看到最下面一行出现一行字符串,但其实并没有那么简单。

首先,在Kliba.asm中定义了一个函数disp_str,用来打印字符串,并且将这个函数导出。
然后在kernel.asm中引入刚刚定义的函数,并将kernel,kliba,string,start链接成kernel.bin并挂载,作为真正的内核程序。
这个代码不仅定义了函数,还使用memcpy函数切换了堆栈和GDT,和之前仅仅打印一个字符的代码相比复杂了许多,但并没有花费很大精力,可见内核的扩展在C语言的帮助下已经简单了许多了。

5. 设计题:修改启动代码,在引导过程中在屏幕上画出一个你喜欢的ASCII图案,并将第三章的内存管理功能代码、你自己设计的中断代码集成到你的kernel文件目录管理中,并建立makefile文件,编译成内核,并引导

1)画出一个ASCII图案
在引导的时候,让他打印两个由字符构成的表情,调用一个打印函数打印如下定义的字符串:

函数还是使用的例子程序中提供的,结果如下:

打印其他的应该是差不多的,就是要记得构造好这个字符的形状。

2)Kernel扩展
扩展原理很简单,主要是中断处理程序的编写问题。之前我们的实验中有过类似的步骤,我们可以直接调用当时的函数。

当然,这里我们不再使用键盘中断,而是使用时钟中断,所以记得修改初始化的值:

其他地方与例子程序没什么很大差别,我们来看一下中断处理程序部分:

为了减少代码修改,我直接把整个函数复制进来了。。。
也就是说,遇到时钟中断的时候,我们的屏幕将根据时钟中断的“节奏”来打印字符串,在一段时间之后的截图如下:

看上去其实挺吓人的,但是从代码实现的角度来说应该是成功了吧。

实验问题:

1.汇编和C的调用方法是怎样的?

将汇编中定义的函数定义为global形式进行导出,将需要使用的函数进行导入;C语言在使用函数之前进行定义。在编译过程中先生成.o文件,并链接所有.o文件成为新文件,作为可执行程序,这个程序既包含汇编文件中的函数也包含C语言中的参数。

2.描述ELF文件格式以及作用


ELF header:用来定义ELF文件各信息,例如Program header table个数与偏移地址。
Program header table:


描述的是一个段在文件中的位置,位置、大小以及它被放进内存后所在的位置和大小。如果我们想把一个文件加载进内存的话,需要的正是这些信息。

3.如何从Loader引导ELF的原理

从Loader引导ELF文件需要经过几个步骤:寻找文件、定位文件、读入内存、转交控制权,其中前三个步骤与是否为ELF文件关系不大,对于要读入内存的文件来说都是需要经过这三个步骤的;最后一个步骤转交控制权则是根据ELF文件头与Program header table中的信息,将内存中的段进行整合并执行、转交控制权。

4.一个内核要能基本使用应该扩展哪些功能,怎么扩展

一个内核是在保护模式中被引导、运行,从实验的角度上说,内核需要接管电脑的控制权,管理计算机上运行的所有程序、进行的所有操作,所以至少应该具有中断管理,线程管理,地址空间和进程间通信等功能。

5.怎么管理内核文件目录?

在之前实验中我们的文件都是散落在一个文件夹里,编译生成的文件也是很混乱,最痛苦的是每次编译、挂载都有很多指令要打。所以我们需要使用make指令来管理内核文件目录。
目前为止我们可以整理成如下所示的结构:

然后,在a.img的路径下添加makefile文件,完成编译、链接、挂载的任务,最后启动bochs则可以达到目的。

Makefile如上所示,使用如上所述的方法和工具则可以很好的管理内核文件和目录。

操作系统——内核雏形相关推荐

  1. 【操作系统】Oranges学习笔记(四) 第五章 内核雏形

    文章目录 5.1 在Linux下用汇编写HelloWord 5.2 再进一步,汇编和C同步使用 5.3 ELF(Executable and Linkable Format) 1. ELF Heade ...

  2. WINCE6.0操作系统---内核(kernel)学习

    ********************************LoongEmbedded******************************** 作者:LoongEmbedded(kandi ...

  3. 操作系统--内核级线程实现

    五段论        `: 进入内核靠的是中断,fork是创建系统进程调用,进程由资源+执行序列组成,而创建执行序列其实就是创建线程. TSS:任务结构段     参考: 操作系统_哈尔滨工业大学_中 ...

  4. 0x300-从头开始写操作系统-内核

    目录 回顾 今日目标 必要工具的安装及介绍 工具一览 工具介绍 GCC Hosted Environment Freestanding Environment Linker C 语言编译(gcc 的临 ...

  5. 1.操作系统——内核

    计算机资源 计算机中资源分为软硬件两类: 其中,硬件资源有 总线:主要负责连接其他设备,是其他设备工作的基础. CPU:中央处理器,负责执行程序和处理数据运算. 内存:负责储存正在运行时的代码和数据. ...

  6. 【操作系统】浅谈OS内核

    公众号「码农小奎」操作系统-内核篇 实际上,计算机体系在经过几十年的迭代更新之后,操作系统的内核离我们已经很遥远了. 无论是对普通用户还是上层软件开发者来说,内核之中有什么已经不太重要了,而用户更关心 ...

  7. 华为操作系统 28 年史

    作者 | 老兵戴辉 本文经授权转自公众号最牛博弈(ID:zngame) 8月9日,东莞松山湖沸腾的一天,华为消费者业务CEO余承东发布了鸿蒙操作系统,中文来自山海经,英文叫HarmonyOS,不是以前 ...

  8. Linux是操作系统吗?GNU/Linux又是什么?

    题记:这篇博文是在阅读Richard Stallman先生的<Linux and the GNU System>之后,并结合自己目前对Linux的认知写成的. 相信很多IT界的学习从业者, ...

  9. Linux内核源代码分析-第三章 内核体系结构概述-1

    第3章 内核体系结构概述 本章从较高层次上对内核进行说明.从顺序上来说,本章首先介绍内核设计目标,接下来 介绍内核体系结构,最后介绍内核源程序目录结构. 3.1 内核设计目标 Linux 的内核展现出 ...

  10. Linux运维基础(硬件和操作系统)

    VMware Workstation的使用: 虚拟机 虚拟计算机 在一个主机上,软件+硬件模拟出的硬件设备,然后在虚拟出来的设备上安装系统,等同于在物理机上的操作! 现代计算机设备的组成部分: 运算器 ...

最新文章

  1. leetcode中求subset、全排列等问题的回溯算法总结
  2. BZOJ 3195: [Jxoi2012]奇怪的道路 | 状压DP
  3. 【JUC系列】Future异步回调模式
  4. java jquery post_jquery js post变量set和get for post
  5. 大数据统计学直观图表(二)
  6. Android监视器概述
  7. (转载)Manacher'sAlgorithm: O(n)时间求字符串的最长回文子串
  8. Ruby设计模式透析之 —— 策略(Strategy)
  9. TMS320C55x的硬件结构
  10. yacc 简易计算机规则,YACC 使用说明——计算器实例.pdf
  11. 智慧园区弱电系统集成建设方案
  12. 《TR-069_Amendment-2》翻译
  13. matlabRC电路实验仿真
  14. 电脑死机,Word忘了保存怎么恢复?(编辑器是WPS)
  15. 虚拟服务器忘记密码,win7系统下VMware虚拟机忘记开机密码的解决方法
  16. DNS隧道通信的检测
  17. 微信公众号编辑菜单栏代码
  18. SQL触发器总结 - sql server 2012数据库基础-触发器及应用-实验报告
  19. 四川途志:抖音直播带货什么产品最好卖?
  20. 自动编解码器的训练与数据识别效果解析

热门文章

  1. 【风控策略】通过查全率和查准率确定cutoff
  2. java 中奖_java的if判断是否中奖了(21)
  3. android 设计psd,如何将PSD设计转换为Android xml?
  4. mysql超卖问题处理_mysql 解决超卖问题的锁分析
  5. 3种方法解决word文档无法编辑
  6. 计算机xp系统ie8,WinXP系统IE8安装失败的解决方法
  7. python描述数据维度的含义_NumPy中的维度(dimension)、轴(axis)、秩(rank)的含义
  8. 卫星高度角和方位角的计算
  9. 内外网数据交换方式有哪些?
  10. CPU卡一卡通解决方案