资源

  1. ucore在线实验指导书
  2. 我的ucore实验代码

题目:完善中断初始化和处理

请完成编码工作和回答如下问题:

  1. 中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?

  2. 请编程完善kern/trap/trap.c中对中断向量表进行初始化的函数idt_init。在idt_init函数中,依次对所有中断入口进行初始化。使用mmu.h中的SETGATE宏,填充idt数组内容。每个中断的入口由tools/vectors.c生成,使用trap.c中声明的vectors数组即可。

  3. 请编程完善trap.c中的中断处理函数trap,在对时钟中断进行处理的部分填写trap函数中处理时钟中断的部分,使操作系统每遇到100次时钟中断后,调用print_ticks子程序,向屏幕上打印一行文字”100 ticks”。

完成这问题2和3要求的部分代码后,运行整个系统,可以看到大约每1秒会输出一次”100 ticks”,而按下的键也会在屏幕上显示。

【注意】除了系统调用中断(T_SYSCALL)使用陷阱门描述符且权限为用户态权限以外,其它中断均使用特权级(DPL)为0的中断门描述符,权限为内核态权限;而ucore的应用程序处于特权级3,需要采用`int 0x80`指令操作(这种方式称为软中断,软件中断,Trap中断,在lab5会碰到) 来发出系统调用请求,并要能实现从特权级3到特权级0的转换,所以系统调用中断(T_SYSCALL)所对应的中断门描述符中的特权级(DPL)需要设置为3。

解答

问题1的回答

问题1:中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?

答:中断描述符表一个表项占8个字节,其结构如下:

  • bit 63..48: offset 31..16
  • bit 47..32: 属性信息,包括DPL、P flag等
  • bit 31..16: Segment selector
  • bit 15..0: offset 15..0

其中第1632位是段选择子,用于索引全局描述符表GDT来获取中断处理代码对应的段地址,再加上第015、48~63位构成的偏移地址,即可得到中断处理代码的入口。

完善idt_init函数

idt_init函数的功能是初始化IDT表。IDT表中每个元素均为门描述符,记录一个中断向量的属性,包括中断向量对应的中断处理函数的段选择子/偏移量、门类型(是中断门还是陷阱门)、DPL等。因此,初始化IDT表实际上是初始化每个中断向量的这些属性。

  1. 题目已经提供中断向量的门类型和DPL的设置方法:除了系统调用的门类型为陷阱门、DPL=3外,其他中断的门类型均为中断门、DPL均为0.

  2. 中断处理函数的段选择子及偏移量的设置要参考kern/trap/vectors.S文件:由该文件可知,所有中断向量的中断处理函数地址均保存在__vectors数组中,该数组中第i个元素对应第i个中断向量的中断处理函数地址。而且由文件开头可知,中断处理函数属于.text的内容。因此,中断处理函数的段选择子即.text的段选择子GD_KTEXT。从kern/mm/pmm.c可知.text的段基址为0,因此中断处理函数地址的偏移量等于其地址本身。

  3. 完成IDT表的初始化后,还要使用lidt命令将IDT表的起始地址加载到IDTR寄存器中。

根据以上分析,及注释中的提示,不难完成编码,如下所示。

extern uintptr_t __vectors[];

/* idt_init - initialize IDT to each of the entry points in kern/trap/vectors.S */
void idt_init(void) {
uint32_t pos;
uint32_t sel = GD_KTEXT; /* along: how to set istrap and dpl? */
for (pos = 0; pos < 256; pos++) {
SETGATE(idt[pos], 0, sel, __vectors[pos], 0);
} SETGATE(idt[128], 1, sel, __vectors[128], 3); lidt(&idt_pd);
}

lab1_result中的代码如下所示。答案有几处地方比我写得好:

  1. 我定义的sel变量是多余的,浪费内存,直接使用GD_KTEXT即可。
  2. 设置DPL时使用DPL_KERNEL, DPL_USER代替0和3,可读性更好。
  3. 将extern __vectors放在函数内部,使其仅在本函数内可见,结构上更合理。(是吗?)

不过这里有个问题:答案设置系统调用的门描述符时,中断向量为什么是T_SWITCH_TOK(121)而不是T_SYSCALL(128)?

/* idt_init - initialize IDT to each of the entry points in kern/trap/vectors.S */
void idt_init(void) {
extern uintptr_t __vectors[];
int i;
for (i = 0; i < sizeof(idt) / sizeof(struct gatedesc); i ++) {
SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);
}
// set for switch from user to kernel
SETGATE(idt[T_SWITCH_TOK], 0, GD_KTEXT, __vectors[T_SWITCH_TOK], DPL_USER);
// load the IDT
lidt(&idt_pd);
}

完善trap函数

trap函数只是直接调用了trap_dispatch函数,而trap_dispatch函数实现对各种中断的处理,题目要求我们完成对时钟中断的处理,实现非常简单:定义一个全局变量ticks,每次时钟中断将ticks加1,加到100后打印"100 ticks",然后将ticks清零重新计数。代码实现如下:

    case IRQ_OFFSET + IRQ_TIMER:
if (((++ticks) % TICK_NUM) == 0) {
print_ticks();
ticks = 0;
}

《ucore lab1 exercise6》实验报告的更多相关文章

  1. [操作系统实验lab3]实验报告

    [感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...

  2. Ucore lab1实验报告

    练习一 Makefile 1.1 OS镜像文件ucore.img 是如何一步步生成的? + cc kern/init/init.c + cc kern/libs/readline.c + cc ker ...

  3. ucore操作系统学习(三) ucore lab3虚拟内存管理分析

    1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...

  4. 《ucore lab3》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:给未被映射的地址映射上物理页 题目 完成do_pgfault(mm/vmm.c)函数,给未被映射的地址映射上物理页.设置访问权限的时候需 ...

  5. 《ucore lab1 exercise5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...

  6. 《ucore lab8》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 完成读文件操作的实现(需要编码) 题目 首先了解打开文件的处理流程,然后参考本实验后续的文件读写操作的过程分析,编写在sfs_inod ...

  7. 《ucore lab7》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码) 题目 完成练习0后,建议大家比较一下(可用meld等文件dif ...

  8. 《ucore lab6》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 使用 Round Robin 调度算法(不需要编码) 题目 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件) 个人完成 ...

  9. 《ucore lab5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...

  10. 《ucore lab4》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:分配并初始化一个进程控制块 题目 alloc_proc函数(位于kern/process/proc.c中) 负责分配并返回一个新的str ...

随机推荐

  1. 实现一个简易版webpack

    现实 webpack 的打包产物 大概长这样(只把核心代码留下来): 实现一个简版的webpack 依葫芦画瓢,实现思路分2步: 1. 分析入口文件,把所有的依赖找出来(包括所有后代的依赖) 2. 拼 ...

  2. redis应用场景,缓存的各种问题

    缓存 redis还有另外一个重要的应用领域——缓存 引用来自网友的图解释缓存在架构中的位置 默认情况下,我们的服务架构如下图,客户端请求service,然后service去读取mysql数据库 问题存 ...

  3. #C++初学记录(N皇后#回溯递归)

    <font size=5 face"微软雅黑">N皇后Problem Description <font size=4 face"微软雅黑"& ...

  4. JEECG MiniDao优劣

    Minidao 1.5.1 - 我认为这是一个不严谨的错误 - andotorg的个人空间 - OSCHINAhttps://my.oschina.net/antsdot/blog/1800832 M ...

  5. PHP判断文件大小是MB、GB、TB...

    <?php date_default_timezone_set ("PRC" ); function getFilePro($fileName){ if (!file_exi ...

  6. c#反射动态创建窗体

    根据窗体的名称动态创建窗体 Assembly assembly = Assembly.GetExecutingAssembly();             // 实例化窗体 try { Form f ...

  7. Vue 及双向数据绑定 Vue事件 以及Vue中的ref获取dom节点

    <template> <div id="app"> <h2>{{msg}}</h2> <input type="te ...

  8. Opencv加载网络图片

    opencv加载网络图片 #include <iostream> #include <opencv2/opencv.hpp> using namespace std; usin ...

  9. Qt widget中使用QML自定义电池

    1.效果 2.QML 在资源里新建Mybattery.qml: import QtQuick 2.0 import QtQuick 2.12 Item { id: root property colo ...

  10. 【设备问题】罗技M590鼠标无法连接Macbook Pro问题解决

    问题现象 罗技蓝牙鼠标连接的时候一直显示连接中,但是一直连接不上. 解决方法 长按那个切换模式的按钮,重置下,再点击连接,显示能够连接成功.