一个操作系统的实现55扩充内核实验报告Word格式文档下载.docx
- 文档编号:19481625
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:12
- 大小:403.02KB
一个操作系统的实现55扩充内核实验报告Word格式文档下载.docx
《一个操作系统的实现55扩充内核实验报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《一个操作系统的实现55扩充内核实验报告Word格式文档下载.docx(12页珍藏版)》请在冰豆网上搜索。
1、扩充内核
2、了解如何将c语言和汇编语言结合起来
3、进一步了解中断机制
(二)实验内容
认真阅读章节资料,了解如何导入导出全局变量,在c语言和汇编之间传递参数,并且了解makefile文件的语法,学会变异和链接整个操作系统工程。
掌握中断处理的添加。
2、实验环境及实验步骤
(本次实验所使用的器件、仪器设备等的情况;
具体的实验步骤)
实验环境:
1.ubuntu12.04
2.bochs、freedos以及一系列实验过程中需要用到的文件。
实验过程分析
(详细记录实验过程中发生的故障和问题,进行故障分析,说明故障排除的过程及方法。
根据具体实验,记录、整理相应的数据表格、绘制曲线、波形等)
=================================================================
5.5.1切换堆栈和gdt
首先要了解全局变量的导入和导出
导出:
global
导入:
extern
首先在start.c中有一个cstart()函数。
使用memcpy函数将LOADER中的GDT复制到新的GDT中。
其他步骤地具体含义我已经写在了注释里。
Memcpy函数我们都非常熟悉。
memcpy(目的,源,长度)
在kernel.asm中我们导入并调用它
并且切换堆栈
就完成了我们的目标
编译后运行是没有什么反应的。
我们把显示字符串的代码disp_str加进来,就可以了。
这是第三章的内容。
在start.c中调用它即可
================================================================
5.5.2整理文件夹
整理以后觉得好像更进了一步,至少可能上去像那么一回事了
===============================================================
5.5.3Makefile
用mekafile文件可以直接编译链接整个操作系统,就不用每次都要敲很多命令了。
makefile最重要的语法是:
target:
prerequisites
command
意思是要想得到target,要执行command.
target依赖于prerequisites,prerequisites中至少有一个文件比target文件新时,command才被执行
直接输入make的话也可以,会从第一个名字所代表的动作开始执行。
之后将makefile直接放到父目录里。
代码5.33(g/makefile)添加了一些功能,例如反汇编。
通过makebuilding或者makeimage,可以直接把引导扇区、loader.bin和kernel.bin写入虚拟软盘
我们来试一试
会报错。
为什么呢?
因为我们是64位操作系统。
ld指令有一个选项:
--oformat
output_format,用于指定输出文件的格式。
输入文件./kernel/kernel.o等是elf32格式,当前系统是64位,而ld默认生成的文件格式是elf64-x86-64;
默认生成的文件格式是elf64-x86-64
所以可以在gcc后面加-m32,在ld后面加-melf_i386,如图
就可以成功make
接着再执行bochs那些
成功
5.5.4添加中断处理
接下来我们要干吗呢?
重大目标应该是实现一个进程。
进程必须是可控制的,所以就涉及到进程和操作系统之间的转换。
因为只有一个cpu,所以同一时刻是客户进程和操作系统进程之一在运行。
所以要实现进程,需要一种控制权转换机制,这种机制就是中断
近期目标:
添加中断处理
要做的工作有两项:
设置8259a和建立idt
(1)在i8259.c中设置了8259a,设置8259a是为了设置某些中断请求是否屏蔽以及不同中断对应的中断向量号。
我们要用到kliba,asm中的out_byte函数(对端口写)另外还有in_byte(读)
声明都放在/include/proto.h中
(2)然后还要修改makefile。
1、添加新目标i8259.o2、kernel/start.o依赖关系稍有变化。
gcc–M可以自动生成依赖关系
(3)初始化idt_ptr,和gdt差不多。
全局变量声明都放在/include/global.c中了。
GATE的定义在protect.h中,idt[IDT_size]是一个门描述符数组,定义在global.h中。
所以&
idt为idt首地址。
(4)在kernel.asm中加载idt_ptr到idtr
但是idt中还没有内容。
对异常处理的总体思想:
如果有errorcode,直接把向量号压栈,然后执行一个函数exception_handler;
如果没有erorcode,则先压入一个0xFFFFFF,再把向量号压栈并随后执行exception_handler。
原型:
exception_handler(intvec_no,interr_code,inteip,intcs,inteflags);
发生中断后,
(1)从中断信息中取得中断类型码。
(2)标志寄存器eflags的值入栈,因为在中断过程中要改变标志寄存器的值,所以先将其保存在栈中。
(3)设置标志寄存器IF和TF位为0,为了防止在此中断中再来其他外部中断。
(4)cs,eip,errorcode入栈。
(5)根据中断类型码在IDT中找到中断门(执行代码)。
以上是硬件做的
我们怎么写才能让硬件去IDT中找到相应的描述符然后去执行中断处理代码呢?
(6)首先要初始化描述符。
中断向量值和类型是在protect.h中定义的。
以divide为例
再在protect.c中
调用是这样的(在protect.c中的init_prot函数中,init_8259a()也在这里被调用)
所以就可以用某个描述符填充idt的对应位置
因此init_prot函数中,咱们就把8259a和idt设置好了
那么divide_error是什么呢?
对,就是这儿了:
(kernel.asm)
将这个标号的地址导出,这就相当于把中断处理的代码地址放到相应描述符的基址中了。
这样硬件就可以根据向量号找到相应描述符,再根据基址去找到相应的代码段了
那么我们来看看divide_error这儿干了什么,哦,它没有errorcode,所以我们自己压一个0xffffffff,然后将中断向量压栈,跳到exception标号地址。
是个什么?
先调用exception_handler函数(protect.c)
还记得前面说的硬件把cs,eip,errorcode(如果有的话)入栈了吗?
然后我们自己压了向量号,这就是我们传的参数啦。
之后就是一系列打印信息,很简单啦。
然后我们又回到exception
为什么要让esp加上8呀?
因为eip上面压着错误码和向量号。
我们要让栈顶指向它。
目前为止程序就停住了。
我们新编写的函数有:
disp_color_str()(kliba.asm)为了显示带颜色的字符串
disp_int()(klib.c)为了显示整数
其中用到itoa()也在klib.c中,为了将整数转换成字符串
至此,idt添加的差不多了。
在start.c中调用init_prot()
就成功设置好idt喽!
但是再运行是没有效果的!
因为没有发生中断啊。
我们自己来一个。
ud2指令可以产生#UD异常。
在kernel.asm里加上就可以看到异常了
实验一下,发现报错
上网查了一下,发现要在cflag后面加上
加上后make,然后运行
不过我们并没有真正开始使用8259A。
因为这个中断时我们自己产生的。
8259A可以挂接15个外设,我们也应该有15个中断处理程序。
所有中断都会触发一个函数spurious_irq()
只是把irq号打印出来而已
然后在protect.c中设置idt
在i8259.c中打开键盘中断
在kernel.c中设置IF位
再运行,敲击键盘,会出现中断
四、实验结果总结
这次实验主要用到了以前几次实验的知识积累,将它们综合起来。
比较难一点的应该算是c语言和汇编之间的传递和结合。
不过理清了它们之间的关系也可以掌握一个脉络了。
小组分工:
大家各自都将实验做了一遍。
报告撰写:
吴双可
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 一个 操作系统 实现 55 扩充 内核 实验 报告