OS-lab3
OS-lab3
lab2之后,我们能够通过MMU访问内存了,不过操作系统最重要的是能够让进程运行。
include
env.h
定义了进程控制相关的变量,如进程数量
NENV、进程状态ENV_FREE等、进程控制块Env、创建进程的宏函数ENV_CREATE、ENV_CREATE_PRIORITY等,以及一些在env.c中完成的函数。trap.h
主要定义了用于保存异常现场的结构体
Trapframe,以及方便取出数据的一些宏定义如TF_REG、TF_EPC等。stackframe.h
利用汇编定义了一些处理异常时常用的操作,如开关中断的
STI和CLI,保存现场恢复现场的的SAVE_ALL、RESTORE_ALL、RESTORE_SOME等,取出内核栈地址的get_sp。
lib
env.c
首先是定义了一些全局变量,
envs使进程控制块数组,curenv指当前的进程,env_free_list代表空闲的进程控制块,env_shed_list指正在运行的进程队列,用于进行调度。mkenvid用于给一个进程建立进程号。具体做法是将该进程的进程控制块偏移和一个静态变量next_env_id结合起来。
envid2env用于找出给定的进程号对应的进程控制块。首先判断这个进程号是否为0,即该进程是否为当前进程curenv,若是则直接将curenv赋给*penv,若不是,则利用ENVX在envs中找出这个进程号对应的控制块;若这个进程状态为不可运行或env_id不为指定的envid则报错;检查checkperm,如果被置位,则需要检查当前的进程curenv是否能够操作找到的进程控制块,即检查这个进程是否为curenv或curenv的子进程,若不是则报错;将*penv赋值并返回。上面两个函数是对进程进行处理过程中经常使用的函数。
env_init函数用于初始化进程控制的一些变量。首先通过LIST_INIT初始化env_sched_list和env_free_list然后将envs中的控制块状态都设为不可运行,再反向插入env_free_list中,这样才能够保证顺序。
env_setup_vm函数用于初始化一个新进程的页表。首先分配一页存放页目录,并设置env_cr3为页目录物理地址;然后将映射到UTOP以下的页目录项清零,将UTOP以上的复制为boot_pgdir的值,这样在切换为内核态时就能直接使用这一片内存,不需要修改env_cr3;最后将UVPT项设置为env_cr3和相应的标志位。
env_alloc函数用于创建一个新进程。与分配内存类似,首先需要检查env_free_list是否为空,然后获得一个空的进程控制块;使用env_setup_vm给新进程设置页表;给进程控制块的成员赋值;将这个进程控制块从env_free_list中删掉。上面的三个函数是用于初始化和创建进程的函数,核心是
env_alloc。load_icode_mapper函数用于将二进制文件加载到内存中,主要需要处理.text段、.data段和.bss段。
这两部分处理方式类似,区别在于
.bss段需要用bzero进行清零。具体流程则是用page_alloc分配一页内存,用page_insert加入到进程的页表中,使用bcopy或bzero对这一页内容进行操作。需要注意的是,这里使用的全部为虚拟地址。
load_icode函数完成了将二进制文件加载到进程地址中并设置pc值的完整过程。首先是分配一页作为进程的用户栈;然后使用load_elf加载二进制映像;最后设置env_tf.pc,即进程开始执行的pc值。
env_create_priority函数完成了完整的创建进程并加入运行队列的功能。首先是用env_alloc分配一块空闲的进程;然后给env_pri赋值;再用load_icode加载二进制映像;最后使用LIST_INSERT_HEAD把进程加入到env_sched_list中。
env_create函数直接调用了env_create_priority函数,将优先级设为1。
env_run函数用于切换当前进程为指定进程。首先是保存curenv的运行现场,通过bcopy将TIMESTACK中存放的运行时信息复制到env_tf中,并设置env_tf.pc的值为env_tf.cp0_epc;接着给curenv赋值并增加env_runs;然后调用lcontext切换进程的地址;最后使用env_pop_tf恢复准备执行的进程的上下文。到这里为止就完成了从分配一个空闲进程块到加载程序到切换运行的全部过程。
env_free函数用于释放一个进程的空间。首先是找到UTOP下已经映射的页目录项,使用page_remove将这个页目录项对应的页表中所有的映射移除;然后将页目录项清零并减少引用;遍历结束后将页目录也清零并减少页目录所在页面的引用;最后修改进程状态并从env_sched_list中移除加入到env_free_list中。
env_destroy函数用于杀死指定的进程并调度运行一个新进程。先用env_free杀死进程,再判断如果这个进程为curenv,则将KERNEL_SP复制到TIMESTACK中,执行内核的调度函数。上面这两个函数用于结束进程。
最后的
env_check用于检查上述函数功能是否正确。env_asm.S
定义了env.c中使用的两个函数
env_pop_tf和lcontext。env_pop_tf用于恢复进程的执行现场。首先是恢复CP0_ENTRYHI;接着设置CP0_STATUS关闭全局中断;然后恢复通用寄存器;最后再恢复CP0_STATUS。
lcontext函数用于切换地址空间。就是将进程的页目录地址存入到mCONTEXT中,这个变量专门用于存放页目录地址。kclock.c
这个文件用于设置系统时钟。
kclock_asm.S
这里定义完成了设置时钟的函数
set_timer。主要任务就是将特定的数值写入到时钟的地址,然后设置CP0_STATUS。sched.c
完成了调度函数
sched_yeild,采用时间片轮转算法。首先取得当前调度队列的首个进程,判断这个进程是否为空或是否不可执行或时间片是否用完,若满足则需要进行调度;若进程不为空,则将这个进程从当前队列移动到另一个队列尾部;然后判断当前队列是否为空,若为空则需要切换队列,即修改point;循环查找当前的队列,直到找到不为空且可运行的进程,将时间片的值设为优先级,然后进入env_run切换执行。在查找过程中,需要注意队列空了之后需要切换到另一个队列继续这个查找,此外还需处理状态为不可运行和已释放的进程。
另外还修改了tools的链接文件,设置了异常处理地址;在start.S中增加了异常分发代码。
实验流程
在init.c中使用了ENV_CREATE创建了两个进程,接着进入env_create函数完成了创建进程并加入调度队列。在遇到时钟中断或需要切换的时候,首先会触发异常,跳转到start.S中检查触发异常的原因,即时钟中断,接着通过exception_handlers载入处理这种中断的函数timer_irq,接着转到sched_yeild函数进行调度。
OS-lab3的更多相关文章
- 【bug记录】OS Lab3 踩坑记
OS Lab3 踩坑记 Lab3在之前Lab2的基础上,增加了进程建立.调度和中断异常处理.其中测试包括进程建立以及进程调度部分. 由于是第一次做bug记录,而且是调试完bug后再做的记录,所以导致记 ...
- MIT 6.824 : Spring 2015 lab3 训练笔记
摘要: 源代码参见我的github:https://github.com/YaoZengzeng/MIT-6.824 Lab3: Paxos-based Key/Value Service Intro ...
- 【bug记录】OS Lab4 踩坑记
OS Lab4 踩坑记 Lab4在之前Lab3的基础上,增加了系统调用,难度增加了很多.而且加上注释不详细,开玩笑的指导书,自己做起来困难较大.也遇到了大大小小的bug,调试了一整天. 本文记录笔者在 ...
- ucore操作系统学习(三) ucore lab3虚拟内存管理分析
1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...
- [OS] 操作系统课程(三)
工具 源码阅读:understand 源码文档自动生成工具:Doxygen 编译环境:gcc 运行环境:x86机器或QEMU 调试工具:QEMU+(GDB or IDE) IDE:Eclipse-CD ...
- NodeJs之OS
OS Node.js提供了一些基本的底层操作系统的模块OS. API var os = require('os'); console.log('[arch] 操作系统CPU架构'+os.arch()) ...
- Node.js:OS模块
os模块,可以用来获取操作系统相关的信息和机器物理信息,例如操作系统平台,内核,cpu架构,内存,cpu,网卡等信息. 使用如下所示: const os = require('os'); var de ...
- Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验
Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...
- Mac OS 使用 Vagrant 管理虚拟机(VirtualBox)
Vagrant(官网.github)是一款构建虚拟开发环境的工具,支持 Window,Linux,Mac OS,Vagrant 中的 Boxes 概念类似于 Docker(实质是不同的),你可以把它看 ...
- Mac OS、Ubuntu 安装及使用 Consul
Consul 概念(摘录): Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发现的方案,比如 Airbnb 的 SmartStac ...
随机推荐
- 面向对象程序设计(三):C++模板operator Type类型转换
学习算法的时候遇到了一个不认识的写法,去网上查了查,看到有一篇写的挺好的,转载过来了 C++隐式类型转换运算符operator type()用法详解 对象向基本数据类型转换: 点击查看代码 #incl ...
- Java的两个好用的工具包 Apache commons
Apache commons 介绍 这是apache commons lang3的工具类的截图 这个工具,小皮一般用在业务层较多 这是apache commons codec下面的工具 这个工具包,今 ...
- 【译】使用 ML.NET 进行机器学习 - 集群完整指南
原文 | Nikola M. Zivkovic 翻译 | 郑子铭 在之前的几篇文章中,我们探索了一些基本的机器学习算法.到目前为止,我们介绍了一些简单的回归算法,分类 算法.我们使用 ML.NET 实 ...
- Struts2文件配置介绍
Struts2文件配置介绍 struts2 structs.xml文件配置 标签 package标签 <?xml version="1.0" encoding="U ...
- Postman操作指南
基本使用 基本使用在这里不做记录,大多数人下载完就会用.这里记一下重点. 抓包浏览器 浏览器安装插件postman interceptor:插件在postman-interceptor界面最下面提示的 ...
- git添加多账户(附带tortoiseGit多账号使用)
近期想在公司电脑上开发自己项目,但是电脑上已经配置过一个gitlab账户了,现在想要把自己的git账户也加进来,方便代码控制. 因为git用的比较少,还不太熟悉,都是网上找资料,边看边学边做,如有不对 ...
- 通过 Pulsar 源码彻底解决重复消费问题
背景 最近真是和 Pulsar 杠上了,业务团队反馈说是线上有个应用消息重复消费. 而且在测试环境是可以稳定复现的,根据经验来看一般能稳定复现的都比较好解决. 定位问题 接着便是定位问题了,根据之前的 ...
- C#/.net程序调用python
C#/.net程序调用python C#的优势在于window下的开发,不仅功能强大而且开发周期短.而python则有众多的第三方库,可以避免自己造轮子,利用C#来做界面,而具体实现使用python来 ...
- IIS SSL认证流程& url重写
一.SSL认证 也就是我们常说的服务器认证,为的是启动加密传输协议https,步骤如下: 1.生成证书请求 进入IIS,选择服务器的服务器证书设置选项, 创建证书申请,填值如图所示 选择加密服务提供程 ...
- Sidecar-详解 JuiceFS CSI Driver 新模式
近期发布的 JuiceFS CSI Driver v0.18 版本中,我们提供了一种全新的方式访问文件系统,即 JuiceFS 客户端以 Sidecar 方式运行于应用 Pod 中,且客户端与应用同生 ...