Exercise 1.Implement round-robin scheduling in sched_yield() as described above. Don't forget to modify syscall() to dispatch sys_yield().
修改kern/sched.c文件的sched_yield()函数
注意:
1、注意起始env的选择一定是当前env的下一个,如果没有env或者env到了最后就从第1个env开始,第0个env作为idle使用的。
2、循环次数,由于不遍历第0个env,所以总共最多循环NENV-1次,这时候整好循环到当前env(如果有的话)
Exercise 2. Implement the system calls described above (sys_exofork, sys_env_set_status, sys_page_alloc, sys_page_map, sys_page_unmap) in kern/syscall.c. You will need to use various functions in kern/pmap.c and kern/env.c, particularly envid2env(). For now, whenever you call envid2env(), pass 1 in the checkperm parameter. Be sure you check for any invalid system call arguments, returning -E_INVAL in that case. Test your JOS kernel with user/dumbfork and make sure it works before proceeding.
修改kern/syscall.c中如下函数
注意返回值的问题,子进程要返回0,所以要把0放到eax中,子进程开始运行的时候从内核返回到用户层就是把eax作为返回值。
注意status的值要在限定的范围内。
注意perm的权限,有些一定要置位,有些一定不能有。
主要还是传入参数的安全性/合法性检测
一个page_remove就把活儿轻松搞定
最后还需要注意的是,在syscal()函数里,也要把对应的系统调用安排好。
Challenge 1 Add a less trivial scheduling policy to the kernel, such as a fixed-priority scheduler that allows each environment to be assigned a priority and ensures that higher-priority environments are always chosen in preference to lower-priority environments. If you're feeling really adventurous, try implementing a Unix-style adjustable-priority scheduler or even a lottery or stride scheduler. (Look up "lottery scheduling" and "stride scheduling" in Google.)
Write a test program or two that verifies that your scheduling algorithm is working correctly (i.e., the right environments get run in the right order). It may be easier to write these test programs once you have implemented fork() and IPC in parts B and C of this lab.
给进程调度加入优先级。这个问题实现起来是很轻松的,在内核开辟一块进程调度队列即可。不过原本代码根本没有考虑优先级,所以调度部分sched_yield()要重写,各种进程状态改变的部分也要加入优先级部分,写起来比较麻烦。但是简单的可以用数组来实现,这样每次进程切换的时候都会遍历一次进程数组,这个简单的实现可以参考XV6的进程优先级实现部分。下面说的是进程队列的实现
1、进程结构体要加入优先级成员,并新建一个进程list类型,或者直接用数组。
2、在内核建立进程队列。
3、在进程创建的时候给与初始优先级。
4、在进程切换的时候,当前进程优先级变为初始值入队,其余进程优先级递增(可加权递增),在进程队列中选择最大的一个运行。
5、进程在变为非runnable(阻塞)的时候要从进程队列删除,恢复的时候加入,为了提高程序的响应速度,可以在恢复的时候增加优先级。
这个模型的优点是实现方便,操作灵活,在并发不多的环境下性能也不错。
Challenge 2 The JOS kernel currently does not allow applications to use the x86 processor's x87 floating-point unit (FPU), MMX instructions, or Streaming SIMD Extensions (SSE). Extend the Env structure to provide a save area for the processor's floating point state, and extend the context switching code to save and restore this state properly when switching from one environment to another. The FXSAVE and FXRSTOR instructions may be useful, but note that these are not in the old i386 user's manual because they were introduced in more recent processors. Write a user-level test program that does something cool with floating-point.
给中断加入保存浮点寄存器的功能。
1、给inc/trap.h文件中的Trapframe结构体新增char tf_fpus[512]成员,并新增uint32_t tf_padding0[3]用来对齐。
2、修改kern/trapentry.S文件中的_alltraps函数,加入保存fpu寄存器的功能
3、修改kern/env.c文件env_pop_tf()函数,加入恢复fpu功能
4、测试用例是修改的user/dumbfork.c的umain()函数。
注意
1、利用父子进程不停的切换来测试浮点寄存器有没有被保存。
2、gcc 4.5.1 x86版本 -03优化好像对于浮点运算提供了保护功能,如果运算后有函数调用会浮点数保存回去(或者是没有达到优化条件?),这样即使函数内部使用了浮点寄存器也不会影响到外面。所以只好用嵌入汇编测试了,不知道有没有编译参数可以调整。当我把上面循环手工展开,把sys_yield()改成直接inline到系统调用时,只用C代码也可以达到测试的效果。
Challenge 3 Add the additional system calls necessary to read all of the vital state of an existing environment as well as set it up. Then implement a user mode program that forks off a child environment, runs it for a while (e.g., a few iterations of sys_yield()), then takes a complete snapshot or checkpoint of the child environment, runs the child for a while longer, and finally restores the child environment to the state it was in at the checkpoint and continues it from there. Thus, you are effectively "replaying" the execution of the child environment from an intermediate state. Make the child environment perform some interaction with the user using sys_cgetc() or readline() so that the user can view and mutate its internal state, and verify that with your checkpoint/restart you can give the child environment a case of selective amnesia, making it "forget" everything that happened beyond a certain point.
增加系统调用,提供进程快照的功能。要提供完整的快照功能,除了要保存进程的全部数据,如果考虑到进程不掉用exec来替换代码文本外,需要保存以下数据
1、进程全局变量
2、进程用户栈
3、进程环境变量Env结构体
内核栈数据不需要保存,因为没有内核抢占功能,内核栈是共用的,如果想保存全局变量的话需要修改载入程序文件处的函数用来保存一些信息,而且不同的全局变量所在段大小是不同的,在用户空间分配也比较麻烦,所以这里暂时只保存用户栈和Env结构体,也可以实现简单的进程快照功能。具体实现如下:
1、在inc/env.h中声明进程状态的结构体
2、修改inc/syscall.h中的enmu,增加sys_proc_sav和sys_proc_rst两个调用号
3、在kern/syscall.c中新增两个函数sys_proc_save和sys_proc_restore分别用来保存和恢复进程状态,并且修改syscal()函数,使得这两个函数处理新增的两个调用号
4、修改inc/lib.h文件,声明两个系统调用的用户接口
5、修改lib/syscall.c文件,实现两个系统调用的用户接口
6、在user/dumbfork.c的基础上修改umain()函数用来测试。
注意:
1、把进程快照保存在用户空间的好处就是父进程可以非常方便的修改用户状态,不好之处就是风险实在太大。也可以把真实数据放入内核,外界用ID代替,就像envid和filedesc一样。
2、这里把进程快照变量定义成了全局变量,不能放在栈上,因为它还要保存的栈数据呢,这样一来就超过栈的大小了。其实也可以实现成在内核分配正好大小的数据返回指针给用户空间,不过由于目前内核对用户空间的内存管理还不够方便(还没实现堆管理),所以就没这么做。
Question 1. In your implementation of env_run() you should have called lcr3(). Before and after the call to lcr3(), your code makes references (at least it should) to the variable e, the argument to env_run. Upon loading the %cr3 register, the addressing context used by the MMU is instantly changed. But a virtual address (namely e) has meaning relative to a given address context--the address context specifies the physical address to which the virtual address maps. Why can the pointer e be dereferenced both before and after the addressing switch?
因为无论是e变量(保存在内核栈上)还是e指向的环境结构体变量(保存在内核数据段)其页映射关系在每个进程的cr3对应的页目录中都是一致的,所以切换cr3不会引发此方面的异常。
分享到:
相关推荐
【MIT 6.828 lab3 完整代码】是麻省理工学院(MIT)操作系统课程6.828“操作系统工程”的第三实验的源码集合。这个实验旨在让学生深入理解操作系统的基本概念,特别是与内存管理和进程调度相关的部分。在进行这个...
在MIT6.828的lab4实验报告中,核心知识点包括多处理器支持、协作式多任务处理、内存映射输入输出、应用处理器(AP)引导程序、CPU私有状态与初始化、大内核锁、轮转调度算法、创建其他进程的系统调用、写时复制...
《MIT 6.828 JOS实验室:深入...总之,MIT 6.828 Lab3是操作系统学习者的一次宝贵实践,通过实际操作,理论知识得以巩固,同时也能提升解决复杂问题的能力。对于有志于操作系统领域的人来说,这是一次不容错过的旅程。
《MIT 6.828 操作系统课程与实验室实践详解》 MIT 6.828 是由美国麻省理工学院(MIT)开设的一门操作系统(Operating System, OS)高级课程,它在清华大学和北京大学等多所顶尖高校中被广泛采用作为操作系统实习...
MIT 6.828 JOS 操作系统Lab1 - Lab5的全部代码。 MIT 6.828 是精典的操作系统公开课程。同时也是我们对系统学习和认知的很好的课程。作者曾经也苦于没有很好的实践方案让自己更深入的了解操作系统和x86体系机构。...
MIT6.828是一门关于操作系统设计与实现的高级课程,其中的Lab4是JOS(J OS, Joy Operating System)操作系统内核编程的一部分。JOS是一个简化版的操作系统内核,设计用于教学目的,让学生能够深入理解操作系统的基本...
这是JOS mit6.828课程的网站资源,为了学习操作系统,但是害怕这门课的教程总是变来变去,并且配置环镜总是变化,所以把除视频和lab1,lab2...lab7的源代码之外的所有网站的资源全部下载下来了,这样就可以安心的学习...
MIT6.828 lab5 报告中包含有具体的基础知识和练习的解析,具有很好的学习价值
mit 6.828 lab1答案 printf.c 里面的是代码的实现 打印8进制数字
在这份操作系统MIT6.828实验报告中,作者李丙昕总结了实验室中比较重要的知识点,并详细讨论了在实验练习中遇到的问题及其扩展内容。报告主要围绕物理页面管理、虚拟内存以及内核地址空间三个核心知识点进行阐述,并...
1.实现mmio_map_region + page_init微调 2.设置每个cpu的内核堆栈 3.设置CPU的特殊寄存器值 4.设置锁 5.实现RR调度 6
这是MIT6.828的个人学习笔记,纳入非计算机专业出身,可能会有太多纰漏,烦请大神斧正。个人认为,操作系统是计算机专业课之中综合性很强的一门课,牵涉面广,知识点多,相对也非常难学。 大名鼎鼎的6.828的最大的...
在这个“git qemu mit6.828”项目中,我们可以推测这可能是一个关于麻省理工学院(MIT)6.828课程的实践项目,该课程通常涉及操作系统原理和实现。下面我们将详细讨论 Git 和 QEMU 的相关知识点。 **Git** Git 是一个...
- **课程网站**:[https://pdos.csail.mit.edu/6.828](https://pdos.csail.mit.edu/6.828) - **讲座内容**: - 操作系统的基本概念。 - 对传统操作系统xv6的深入分析。 - 基于xv6的编程作业实践。 - 最近的研究...
MIT 的JOS系统,资源里面是lab2的修改后源码
《MIT6.828操作系统课程实验与源码解析》 MIT6.828是麻省理工学院(MIT)开设的一门高级操作系统课程,它深入探讨了操作系统的设计与实现,为学生提供了丰富的实践机会。这门课程的核心部分是实验,通过实际编写和...
《MIT操作系统6.828课程可执行jos实验代码详解》 MIT的6.828操作系统课程,全称为“操作系统工程”(Operating System Engineering),是全球计算机科学领域内享有盛誉的一门课程。该课程的重点在于实际操作系统的...
git clone http://web.mit.edu/6.828/www ``` 安装完成后,需要确保QEMU的版本与6.828课程指定的版本一致,以避免后续实验过程中出现不必要的问题。 #### 四、总结 通过上述步骤,学生们可以在自己的计算机上...
【MIT 6.828课程详解:操作系统精髓与实现】 MIT 6.828课程,全称为“操作系统精髓与实现”(JOS操作系统),是麻省理工学院(MIT)计算机科学与电气工程系的一门核心课程。该课程旨在深入讲解操作系统的基本原理和...