注:源代码参见我的github: https://github.com/YaoZengzeng/jos

Part A : User Environments and Exception Handling

User Exception:

1、kernel维护了以下三个全局变量和environment有关的全局变量

struct Env *envs = NULL;		// All environments
struct Env *curenv = NULL; // The current env -->在启动过程中,curenv被初始化为NULL
static struct Env *env_free_list; // Free environment list 数据结构Env定义在inc/env.h中,如下所示:
struct Env {
struct Trapframe env_tf; // Saved registers
struct Env *env_link; // Next free Env
envid_t env_id; // Unique environment identifier
envid_t env_parent_id; // env_id of this env's parent
enum EnvType env_type; // Indicates special system environments
unsigned env_status; // Status of the environment
uint32_t env_runs; // Number of times environment has run // Address space
pde_t *env_pgdir; // Kernel virtual address of page dir
}; env_id:Kernel用一个唯一的id来标示当前正在使用这个Env数据结构的进程(或者说正在使用envs中这个特定的slot的environment)。当一个用户进程终止的时候,kernel可能会将同一个Env数据结构
重新分配给另一个不同的environment。但是,新的environment仍然会有一个完全不同的env_id,虽然它和旧的environment使用在envs中相同的slot。
env_status:
ENV_FREE:该Env inactive,该结构正在env_free_list中
ENV_RUNNABLE:该Env正在等待CPU运行
ENV_RUNNING:该Env正在CPU上运行
ENV_NOT_RUNNABLE:该Env是active的,但是并不能运行,原因可能是它在等待来自其他environment的IPC
ENV_DYING:僵尸进程,它在下一次陷入kernel的时候会被释放 2、和Unix process类似,JOS的environment结合了"thread"和"address space"。thread由保存在env_tf中的寄存器定义,而address space则由env_pgdir指向的page directory和page table 定义。
在JOS中,不像xv6,每个进程都有单独的kernel stacks。因为在JOS中,每次仅仅只能有一个environment处于kernel中,因此JOS只需要一个kernel stack。 3、
(1)void env_init(void):将envs中的所有environment设置为free,将它们的env_ids设置为0,并且将它们插入到env_free_list
(2)static int env_setup_vm(struct Env *e):初始化environment e的内核部分的virtual memory,分配一个page作为e->env_pgdir的page directory,因为每个environment的kernel部分的
(3)virtual memmory的布局是一致的,因此只需要将kern_pgdir索引高于PDX(UTOP)的部分直接拷贝到e->env_pgdir的相应部分即可。
(4)static void region_alloc(struct Env *e, void *va, size_t len): 为environment e分配len个字节的physical memory,并且将它映射到该environment address space的va处。并且
将va向下对齐,(va+len)向上对齐(对齐即能被PGSIZE整除)
(5)static void load_icode(struct Env *e, uint8_t *binary):为environment e初始化程序,堆栈和处理器标志,简单地说就是将kernel中硬编码写入的程序加载到environment e的地址空间内。
并且为该程序映射一个one page大小的初始栈。
注:类似于boot loader从磁盘中加载加载内核,首先需要读取ELF header,这里将binary做强制类型转换即可
接着将类型为ELF_PROG_LOAD的segment载入内存,其实最快的方法是直接利用memcpy的方法进行内存的拷贝,但是这里存在一个问题,因为此时的page directory依旧是kernel的kern_pgdir,而我们需要将
数据拷贝到environment e自己的address space中,所以这里的操作比较tricky,需要先执行指令"lcr3(PADDR(e->env_pgdir));"进入e的address space,再进行memcpy,之后再"lcr3(PADDR(kern_pgdir));"
转换回来即可。最后,我们需要制定environment e的执行入口,其实就是初始化e->env_tf.tf_eip,一般该值为0x800020。
(6)void env_create(uint8_t *binary, enum EnvType type): 利用env_alloc获取一个新的environment,并且利用load_inode将binary载入该env的address space,最后设置environment的type。
(7)void env_run(struct Env *e):切换上下文,将当前运行的environment设置为e。
(8)env_pop_tf(struct Trapframe *tf): 将tf的内容载入寄存器,当'iret'指令执行时,离开kernel,开始执行environment的代码。 Exception Handling:
1、exception和interrupt都是受保护的控制转换(protected control transfer),它能让处理器从用户模式转换到内核模式(CPL=0),从而能够避免用户态的代码影响到kernel或者其他environment的代码。
在x86体系中,interrupt是由处理器之外异步的事件导致的控制转换,例如外设IO的消息等等,而exception是由当前正在运行的代码导致的控制转换,例如访问非法内存等等。 2、为了保证exception/interrupt导致的控制转换确实是受到保护的,那么处理器必须保证在严格控制的条件下才能进入kernel。在x86中,下面两种机制确保了这一切:
(1)The Interrupt Descriptor Table:x86规定了256种不同的interrupt和exception能进入kernel,它们每一个都有自己的interrupt vector。一个vector是一个0到255的数字。CPU使用vector作为
处理器interrupt descriptor table (IDX)的索引,而IDX存放在内核私有的内存里,通过IDX的每个表项,处理器能够得到:
一、EIP:指向处理该类型exception的内核代码。二、CS寄存器的值,其中的0-1位指定了exception handler运行的级别。
(2)The Task State Segment:在处理interrupt和exception之前,处理器需要将当前正在运行代码的状态保存起来,例如寄存器EIP和CS的值,并且为了防止恶意代码的攻击这些状态值存放的地方不能被用户态的代码访问。
因此,当x86执行interrupt或trap之前,运行等级会从用户态转化为内核态,并且会切换到内核内存中的一个stack。一个叫做task state segment(TSS)的数据结构标示了这个stack的segment selector和address。
当执行异常处理的时候,处理器先将SS,ESP,EFLAGS,CS,EIP以及一个可选的error code压栈,接着从interrupt descriptor中加载CS和EIP,最后将ESP和SS指向上述的stack。 3、在x86中所有的synchronous exception使用0到31的interrupt vectors,对应IDT的0到31,例如缺页异常就是vector 14。interrupt vector大于31的,只能被software interrupts,通常由int指令引起,或者
其他一些asynchronous hardware interrupts引起。 4、
(1)、处理器切换到TSS中SS0和ESP0指定stack。在JOS它们的值分别为GD_KD,KSTAKTOP
(2)、将SS,ESP,EFLAGS,CS,EIP一次入栈(有些exception可能会将error code入栈)
(3)、处理器从相应的IDT中获取CS:EIP,执行相应异常处理的代码 5、当系统执行一个嵌套的异常时,此时已经处在内核模式,因此它不需要切换堆栈,并且不用保存老的SS和ESP寄存器,只需要将老的EFLAGS,CS,EIP(如果还有error code)入栈即可。

MIT jos 6.828 Fall 2014 训练记录(lab 3)的更多相关文章

  1. MIT jos 6.828 Fall 2014 训练记录(lab 6)

    源代码参见我的github: https://github.com/YaoZengzeng/jos 在这个实验中将实现一个基于Intel 82540M(又称E1000)的网卡驱动.不过,一个网卡驱动还 ...

  2. MIT jos 6.828 Fall 2014 训练记录(lab 4)

    源代码参见我的github: https://github.com/YaoZengzeng/jos Part A: Multiprocessor Support and Cooperative Mul ...

  3. MIT jos 6.828 Fall 2014 训练记录(lab 2)

    注: 源代码参见我的github:https://github.com/YaoZengzeng/jos Part1 : Physical Page Management mem_init函数: /*该 ...

  4. MIT jos 6.828 Fall 2014 训练记录(lab 1)

    注: 源代码参见我的github:https://github.com/YaoZengzeng/jos Part 1: PC Bootstrap +------------------+ <- ...

  5. MIT jos 6.828 Fall 2014 训练记录(lab 5)

    源代码参见我的github: https://github.com/YaoZengzeng/jos File system perliminaries 我们开发的是一个单用户的操作系统,只提供了足够的 ...

  6. MIT 操作系统实验 MIT JOS lab2

    MIT JOS lab2 首先把内存分布理清楚,由/boot/main.c可知这里把kernel的img的ELF header读入到物理地址0x10000处 这里能够回想JOS lab1的一个小问.当 ...

  7. 台州学院maximum cow训练记录

    前队名太过晦气,故启用最大牛 我们的组队大概就是18年初,组队阵容是17级生詹志龙.陶源和16级的黄睿博. 三人大学前均无接触过此类竞赛,队伍十分年轻.我可能是我们队最菜的,我只是知道的内容最多,靠我 ...

  8. MIT 操作系统实验 MIT JOS lab1

    JOS lab1 首先向MIT还有K&R致敬! 没有非常好的开源环境我不可能拿到这么好的东西. 向每个与我一起交流讨论的programmer致谢!没有道友一起死磕.我也可能会中途放弃. 跟丫死 ...

  9. MIT JOS学习笔记03:kernel 02(2016.11.08)

    未经许可谢绝以任何形式对本文内容进行转载! 本篇接着上一篇对kernel的分析. (5)pte_t * pgdir_walk(pde_t *pgdir, const void *va, int cre ...

随机推荐

  1. 重新想象 Windows 8 Store Apps (55) - 绑定: MVVM 模式

    [源码下载] 重新想象 Windows 8 Store Apps (55) - 绑定: MVVM 模式 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 绑定 通过 M ...

  2. 解决死锁SQL

    USE [master]GO/****** Object: StoredProcedure [dbo].[p_lockinfo] Script Date: 04/03/2014 15:12:40 ** ...

  3. 树状数组---Squared Permutation

    BNUOJ   51636 最近,无聊的过河船同学在玩一种奇怪的名为“小Q的恶作剧”的纸牌游戏. 现在过河船同学手有张牌,分别写着,打乱顺序之后排成一行,位置从左往右按照标号. 接下来小Q同学会给出个 ...

  4. ASP.NET Web API获取Model元数据

    using System; using System.Web.Http; using Common; namespace ConsoleApp { internal class Program { p ...

  5. Android5.0新特性——全新的动画(animation)

    全新的动画 在Material Design设计中,为用户与app交互反馈他们的动作行为和提供了视觉上的连贯性.Material主题为控件和Activity的过渡提供了一些默认的动画,在android ...

  6. DOM LOAD测试笔记

    DOM时间:1823ms LOAD时间:4912ms COMP时间:5427ms 1585 4757 5650 1859 3487 3910 1600 4648 5099 1610 4428 4878 ...

  7. touch触摸事件

    事件对象 事件对象是用来记录一些事件发生时的相关信息的对象.事件对象只有事件发生时才会产生,并且只能是事件处理函数内部访问,在所有事件处理函数运行结束后,事件对象就被销毁! W3C DOM把事件对象作 ...

  8. SharePoint Server 2010 & WorkFlow related Limits

    Today, I have come across different workflow related limits for SharePoint Server 2010. Limit Maximu ...

  9. SQL 查询学生缺考情况

    有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录,写一段SQL语句,检索出每个学生缺考的科目.A 学生表(student)字段1 学生号(s_id)字段2 学生名(s_nam ...

  10. Android Studio 项目代码全部消失--出现原因及解决方法

    出现原因,自己把项目地址父层目录文件名修改了,导致原来打开的项目位置不对,代码全部消失.这样就只要关闭项目,打开一下你修改路径下的项目即可.因为原来的项目还在原来的路径下寻找,但是原来的路径发生了改变