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 ...
随机推荐
- 计算机网络12 TCP
1 TCP简介 CP的全称是Transmission Control Protocol,即传输控制协议,TCP工作在传输层上 其职责是:实现主机间进程到进程的通信,其次还需要保证可靠性(不是安全性,换 ...
- 一个比 Redis 性能更强的数据库
给大家推荐一个比Redis性能更强的数据:KeyDB KeyDB是Redis的高性能分支,侧重于多线程.内存效率和高吞吐量.除了性能改进外,KeyDB还提供主动复制.闪存和子密钥过期等功能.KeyDB ...
- sql注入关键字
id=inurl:Produit.php?id=inurl:Profile_view.php?id=inurl:Publications.php?id=inurl:Stray-Questions-Vi ...
- 【TS】函数重载--可选参数--默认参数
可选参数--默认参数 在ts中定义的数据类型,某些情况下只需要传入定义数据类型的一部分参数,比如:id .name.age.address,此时需要修改用户的名称,那么只需要传入id.name就够了: ...
- 磁盘有限,Docker 垃圾很多怎么办
你的电脑上可能 pull 或者 build 了很多 Docker 镜像,但是你不知道怎么清理,本文将介绍如何清理 Docker 垃圾的常见方法. docker prune 你可以通过原生的多种 pru ...
- 【KAWAKO】TVM-使用c++进行推理
目录 前言 修改cpp_deploy.cc文件 修改DeployGraphExecutor()函数 numpy与bin文件的互相转换 numpy转bin bin转numpy 使用CMakeLists. ...
- 【SDOI2015】排序
#include<cstdio> #include<iostream> using namespace std; typedef long long LL; const int ...
- Linux 下安装Nginx两种方法- yum安装 and Centos7下yum安装配置nginx与php
转载csdn: Linux 下安装Nginx两种方法- yum安装_在电脑前深思的博客-CSDN博客 Linux安装Nginx(两种方式)_HHRunning的博客-CSDN博客_linux 是否安装 ...
- 图论之最短路径Dijkstra算法
/** 图论之最短路径Dijkstra算法 */ #include<string.h> #include<stdio.h> #include<vector> #in ...
- 解析关于Tomcat Servlet-request的获取请求参数及几种常用方法
摘要:本文主要讲解Tomcat之Servlet-request请求参数.Servlet转发机制.常用方法 本文分享自华为云社区<浅谈Tomcat之Servlet-request获取请求参数及常用 ...