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 ...
随机推荐
- NetCoreWebApi3.0-------MiniProfiler使用教程
参考博客:ASP.NET Core WebAPI中的分析工具MiniProfiler - LamondLu - 博客园 (cnblogs.com) 注意事项: 1.不要盲目copy别人的代码 var ...
- Sentry 后端云原生中间件实践 ClickHouse PaaS ,为 Snuba 事件分析引擎提供动力
目录(脑图) ClickHouse PaaS 云原生多租户平台(Altinity.Cloud) 官网:https://altinity.cloud PaaS 架构概览 设计一个拥有云原生编排能力.支持 ...
- PDF-XChange Editor
软件简介 PDF-XChange Editor官方版是PDF-XChange的增强版本编辑器,软件完全绿色免费,且功能无限制.PDF-XChange Editor官方版主要提供PDF电子文档的编辑功能 ...
- JS 格式化时间字符串
// 格式时间字符串 formatDateTimeStr(date, type) { if (date === '' || !date) { return '' } var dateObject = ...
- freertos内存pvPortMalloc 和 malloc 区别 ,以及全局变量占用情况
1.FreeRtos占用内存 #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) pvPortMalloc是从configTOTAL_ ...
- 查询自增ID断点的地方
方法一 SELECT id+1 AS ID FROM table WHERE id+1 not in (SELECT id FROM table);
- 优秀PHP程序员技术成长之路
按照了解的很多PHP/LNMP程序员的发展轨迹,结合个人经验体会,抽象出很多程序员对未来的迷漫,特别对技术学习的盲目和慌乱,简单梳理了这个每个阶段PHP程序员的技术要求,来帮助很多PHP程序做对照设定 ...
- Windows打开代理快捷方式
最近使用电脑需要频繁打开关闭网络代理(全局代理会导致一些网站打不开),在想有没有快捷方式,一搜果然有,看来有跟我一样的使用习惯的人. 传统切换代理开关,步骤如下: 设置 => 网络和 Inter ...
- 【FPGA学习】MATLAB和FPGA实现FFT
本博客记录一下在matlab设计和在FPGA平台实现FFT的方法,平台是Xilinx的ZYNQ 参考: COE文件制作与使用 Vivado使用技巧(9):COE文件使用方法 .coe文件生成 在某些I ...
- PHP 调用外部接口
//1.类中定义静态方法 class FtpService{ /** * 请求外网 * @param $url 外网接口url * @param bool $params 参数,拼接字符串 post请 ...