`
talin2010
  • 浏览: 502225 次
  • 性别: Icon_minigender_1
  • 来自: 河北
社区版块
存档分类
最新评论

[MIT6.828] LAB3总结

阅读更多

LAB3:
Q1.What is the purpose of having an individual handler function for each exception/interrupt? (i.e., if all exceptions/interrupts were delivered to the same handler, what feature that exists in the current implementation could not be provided?)
A1.因为目前的中断机制不能给出足够的信息来在一个函数里面识别不同的中断,除非CPU可以自动保存中断向量这样可以分辨中断的数据给函数使用。

Q2.Did you have to do anything to make the user/softint program behave correctly? The grade script expects it to produce a general protection fault (trap 13), but softint's code says int $14. Why should this produce interrupt vector 13? What happens if the kernel actually allows softint's int $14 instruction to invoke the kernel's page fault handler (which is interrupt vector 14)?
A2.int 14 Page Fault并非一个用户可以直接调用的中断,在实现的时候是给与其内核级别DPL,所以用户直接访问的时候会产生保护错误,从而转到int 13 General Protection。如果内核允许用户直接调用int 14,用户调用时不会压入错误码,会导致栈错位。

Q3.The break point test case will either generate a break point exception or a general protection fault depending on how you initialized the break point entry in the IDT (i.e., your call to SETGATE from idt_init). Why? How did you need to set it in order to get the breakpoint exception to work as specified above?
A3.设置断点IDT的DPL为3即可让用户直接调用。

Q4.What do you think is the point of these mechanisms, particularly in light of what the user/softint test program does?
A4.我没看懂这问题问的什么意思,难道是让解释intel 中断权限机制?查手册就好了

E1.修改kern/pmap.c,分配并映射envs数组。
1、在i386_vm_init()内为envs分配空间,参考源文件内pages的分配方式,需要页对齐。


2、在page_init()内设置envs所在页状态为被占用。


3、在i386_vm_init()内映射envs到UENVS虚拟地址。


E2.在kern/env.c文件中,完成以下函数。
1、env_init():初始化env空闲链表env_free_list,并把envs数组全部元素都插入到链表,注意反向插入,使得第一次从链表取内容时返回envs[0]


2、env_setup_vm():初始化一个用户环境的虚拟内存空间。首先要要分配一页内存作为用户空间的页目录,其内容复制内核页目录,然后把VPT和UVPT映射这个页目录,注意要增加某些页的计数,使得这些页面可以正常回收。


3、segment_alloc():给用户空间分配指定大小的内存并映射到指定虚拟地址上,注意处理页对齐这样的操作,出错则panic。


4、load_icode():从指定内存中复制ELF程序到用户空间,并给用户分配栈。需要注意当前函数操作的是用户空间,所以需要使用用户的页目录,进行复制操作。不直接映射到用户空间而是复制的原因在于,这些程序处于内核空间,直接映射可能会让用户有机会操作内核其他数据,不安全。还需要注意的就是有些段的内存大小大于于ELF文件中的大小,多余的部分需要清零。


5、env_create():调用env_alloc()和load_icode()来完成新建用户环境的操作。


6、env_run():运行用户环境,如果当前用户环境和想要运行的用户环境不同,需要切换页表并设置一些其他内容再运行。

E3.阅读intel手册了解异常和中断的处理

E4.修改kern/trapentry.S以及kern/trap.c,定义中断处理函数,并且设置IDT
1、根据kern/trapentry.S和inc/trap.h中的宏来定义异常和中断,算上系统调用共19个。
2、在trapentry.S中添加_alltraps:标号的代码,这是异常和中断传递的共同部分,主要内容是压入寄存器使得栈空间和struct Trapframe相匹配,载入内核数据段,给trap()函数压入%esp作为参数,调用trap,并处理如果trap切换失败返回回来的情况(平衡栈空间)

3、修改kern/trap.c的idt_init()函数来初始化IDT数组,使用SETGATE宏处理不同的异常/中断入口生成IDT。

E5.修改kern/trap.c中trap_dispatch()函数,把页错误分配给page_fault_handler()函数处理
1、只需要根据Trapframe中的trap类型判断是否0x14(页错误),然后调用page_fault_handler即可。
2、这里我使用了一个trap_hdls数组来存储每个中断的处理函数,中断号为下标直接调用,就不用每个中断写一个case或者if那么麻烦了。

E6.修改kern/trap.c中trap_dispatch()函数,把断点分配给monitor()函数处理

E7.添加系统调用处理机制
1、这里为了跟其他中断保持一致,我把syscall()函数原型改成跟其他中断处理函数一样的类型,可以直接在trap_hdls数组中直接定位并调用。
2、理解Trapframe中不同寄存器在系统调用中的作用,有些寄存器是作为参数传递过来的,要分别对待,返回值放到tf_eax中。
3、按照以上指示把kern/syscall.c 中的所有系统调用都在syscall()中注册。



E8.修改用户库文件,使得用户的hello world程序能正常运行
1、修改lib/libmain.c文件,给env变量赋值,这里需要调用sys_getenvid()系统调用来返回一个用户环境ID,把这个ID转化成envs下标,该下表所代表的元素就是env的所指向的内容。

E9.
1、修改kern/trap.c 中页错误处理函数,在内核(tf->tf_cs==GD_KT)发生缺页中断时,painc掉。

2、在kern/pmap.c中实现user_mem_check()函数,用来检测用户对一块内存是否具有指定的权限。用户对高于ULIM的内存没有任何权限。注意页对齐的情况。

3、修改kern/syscall.c ,对于用户传入内核的指针(sys_cputs()),我们要通过user_mem_assert()函数检查用户对这块内存有没有特定权限。


4、修改kern/kdebug.c,对用户空间的数据使用user_mem_check()函数检查当前用户空间是否对其有PTE_U权限。


5、查看breakpoint程序函数调用栈出现页错误原因是:用户栈显示到了最顶端,再往上是没有映射的空间,访问这些空间会导致页错误。

E10.因为E9的第3步所描述的原因,所以这个邪恶的程序没有实现它的企图,被绳之以法。

C1.整理kern/trapentry.S和kern/trap.c中的代码,改变这种有坏代码味道(很多看起来差不多的代码,这意味着我们要重构了)的状态。
1、在trapentry.S中修改TRAPHANDLER,利用.text 和.data伪指令定义一块数据,这块数据保存了异常入口点以及它的属性。
2、在trap.c的idt_init()函数中,利用循环来读取trapentry.S中定义的数据区,这样就减少了idt_init()中的代码重覆数内容。这体现了Unix一个很重要的设计理念:“Don't Repeat Youself”,同样的代码写一遍就可以了,其他都是引用这块代码。这样可以有效防止程序不一致(有的地方修改了,有的地方还没有修改)的情况。

C2.修改kern/monitor.c,给monitor加入单步调试,反汇编等功能。
加入了以下功能:
1、反汇编,移植了bochs内置的反汇编代码,已经作成静态库放到群共享中,其中遇到最大的问题就是C/C++混合编程(用extern "C"搞定)以及标准库依赖(把这些依赖修改为在jos的库函数即可,主要是printf系列,assert断言,可变传参等)(见disassemble()和u()函数)。


2、单步,使用标志寄存器中的trap位来使得每运行一条指令发生一次int 1中断(见 s()函数)


3、继续,把trap标志位清零即可。(见c()函数)


4、单步运行N条指令,原理同单步,但是要用一个静态变量作为指令计数器,如果到了指定数目就会停下来让用户指示下一步操作(见s(),treat_trap())


5、stepover, 就是把call当成一条指令计数的单步,原理同单步,但是需要增加一个层次变量nextflag 用来标示进入了多少层call,遇到ret就会减少一个层次,当nextflag为1的时候才会修改指令计数器(见n(),tread_trap())。

6、断点,原理是用int3指令替换断点位置的代码。说起来比较简单,实际实现起来是很繁琐的(见b(),break_point(),treat_trap())。


(1)首先要判断用户对断点位置内存是否有权限,有则保存断点指令,并替换为int3;
(2)修改反汇编函数,使得在断点所在反汇编区域的时显示的是原指令,而不是int3;
(3)处理当trap位和用户设置的断点相遇时,暂停两次的情况;
(4)当运行到断点位置时要临时禁用断点,并开启trap标志位,使得下次指令执行完毕后中断;
(5)恢复上次执行指令的时候被临时禁用的中断。
在实现上述功能时使用了很多静态变量,这在会造成程序的耦合度增大,结构变得混乱。这些静态变量可以改进成用户环境变量,每个用户程序都有这些调试专用的变量,以及对应函数来操作这些变量,这样结构就变得清晰,多任务的时候也不会出错。不过现在这样还够用,等需要的时候再修改吧。

C3.使用sysenter/sysexit代替int/iret实现系统调用。
阿,这个太麻烦,而且以后的实验也用不到,偷偷懒,不做了啦~

分享到:
评论

相关推荐

    MIT 6.828 lab3 完整代码

    MIT 6.828 lab3的完整代码, 经试验可以完美运行,在写报告的时候可以参考一下。

    MIT6.828 lab4 实验报告

    MIT6.828 lab4 报告中包含有具体的基础知识和练习的解析,具有很好的学习价值

    MIT 6.828 JOS lab3

    MIT 6.828 JOS lab3 附件里存放的是lab3的源代码,修改后滴……

    MIT6.828 lab3

    MIT6.828 lab3 报告中包含有具体的基础知识和练习的解析,具有很好的学习价值

    MIT 6.828 JOS 全部代码

    MIT 6.828 JOS 操作系统Lab1 - Lab5的全部代码。 MIT 6.828 是精典的操作系统公开课程。同时也是我们对系统学习和认知的很好的课程。作者曾经也苦于没有很好的实践方案让自己更深入的了解操作系统和x86体系机构。...

    mit6.828_2011_JOS

    这是JOS mit6.828课程的网站资源,为了学习操作系统,但是害怕这门课的教程总是变来变去,并且配置环镜总是变化,所以把除视频和lab1,lab2...lab7的源代码之外的所有网站的资源全部下载下来了,这样就可以安心的学习...

    mit 6.828(清华北大操作系统实习课使用)

    完成了6个lab必做的execise部分,希望能为大家提供点帮助~

    MIT6.828 lab5 实验报告

    MIT6.828 lab5 报告中包含有具体的基础知识和练习的解析,具有很好的学习价值

    mit 6.828 lab1答案

    mit 6.828 lab1答案 printf.c 里面的是代码的实现 打印8进制数字

    MIT6.828 lab2 实验报告

    报告中具有详细的基础知识和每个练习的对应解释,具有很好的学习价值

    MIT 8.828 jos lab2

    MIT 的JOS系统,资源里面是lab2的修改后源码

    mit6.828_Jos_lab4.rar_jos lab4

    MIT6.828课程JOS的LAB4的源代码。造福大众,从我做起

    peanutzhen#MIT6.828-2017lab#MIT6.828-2017Lab4PartA 学习过程1

    1.实现mmio_map_region + page_init微调 2.设置每个cpu的内核堆栈 3.设置CPU的特殊寄存器值 4.设置锁 5.实现RR调度 6

    JOS2014:MIT 6.828 Lab 1-7 PKU Labs on OS Course Project

    JOS Lab 1 Report [TOC] 总体概述 本次Lab分为对实验环境的配置和熟悉,Bootloader,JOS kernel这三个部分,一步一步引入,对OS启动和初始化的过程进行了学习。 完成情况 Exercise# 01 02 03 04 05 06 07 08 ch 09 ...

    mit cs6.628

    mit cs 6.828 lab

    MIT6.828:实现一个操作系统内核

    MIT6.828是MIT开源的一门操作系统课程-理论与实践相结合的经典。只要你跟着项目一步一步走,做完6个实验,就能实现一个简单的操作系统内核。 每个实验都有对应的知识点供您学习(也可以自行查找资料),学完理论知识...

    jos:在MIT 6.828操作系统工程中使用的jos

    乔斯 MIT 6.828操作系统工程中使用的操作系统。 实验室 实验1:启动PC 实验2:内存管理 Lab3:用户环境 Lab4:抢先式多任务处理 Lab5:文件系统,Spawn和Shell Lab6:网络驱动程序 延期 参考

    MIT lab1 JOS 实验指导书

    MIT lab1 JOS 实验指导书

    mit-jos-2014:jos是mit6.828课程所用的操作系统,此处记录7个Lab的学习笔记

    这个项目我个人是学习MIT6.828的笔记,主要是我自己对课程LAB的解答,如有错误,欢迎大家提问题或拉请求,欢迎一起讨论。 背景 作为程序员,相信很多人都有一个梦想就是自己实验一下操作系统,反正我是有这样想法的...

    jos lab2 源代码

    这个是MIT6.828LAB2的绝对标准的解答,希望能帮助有需要的同学,自己从头到尾弄了一遍,希望大家共同努力

Global site tag (gtag.js) - Google Analytics