OS第六章
OS第七次实验
多进程
添加一个进程体
添加进程B,首先设置i的初值为0x1000,这样来方便程序运行时的时候能区分。其余地方与A一致。
相关变量和宏
Minix中定义了一个数组,叫做tasktab的数组,用于存放一个进程的开始地址,堆栈等。初始化时,只需要for循环读取然后填充到对应的进程表项即可。
- 声明数组类型,s_task,分别为进程体,堆栈大小,已经名字。
- 在global.h中,增加进程数组,task_table。并记得是在头文件中加入引入的结构体。
- 在proc.h中定义进程的堆栈大小以及新的进程B的声明。
- 进行初始化,主要初始化LDT,将人物入口地址,堆栈栈顶赋给对应的进程表。
- 为每个进程都在GDT中分配了一个描述符来用对应进程的LDT。
初始化进程表
for循环读取相关数据
LDT
改成循环就可,就是用初始化段描述符的函数,然后中间用的是段名转物理,线性转物理。
问题,为什么要移位?
修改中断处理程序
原有代码只有进程的保存和恢复而没有进程的切换。我们需要对其进行增加进程切换相关的部分。只需要使esp指向不同的进程表即可。那就是在离开内核栈,为esp赋值之前对p_proc_ready进行赋值即可
创建一个时钟中断的.c函数,作用是打印一个字符。并且p_proc_ready++,到进程表尾则回到第一个。
添加一个任务的步骤总结
- 添加一个进程体
- tasktable添加项
- 在proc.h添加进程栈的大小
- proto.添加函数声明
系统调用
运转过程
- 控制权交给引导扇区
- 加载Loader
- 跳到Loader
- 加载kernel
- 跳到kernel
- 切换到kernel的GDT
- 初始化8259A
- 初始化IDT
- 初始化GDT中的TSS和LDT的两个描述符,以及初始化TSS
- 初始化进程表
- 指定时钟中断处理程序
- 让8259A可以接受时钟中断
- restart
- 进程开始运转
实现简单的系统调用
一个简单的系统调用
- 用get_ticks来统计中断发生的次数。
- 首先在syscall中定义这个调用函数。
- 将eax赋值为_NR_get_ticks.这样OS就可以在中断发生时调用的是这个函数
- 中断号设为了90.只要不和前面的冲突就行。
- 定义INT_VECTOR_SYS_CALL对应的中断门。
- 修改save,将eax改成esi
- 在kernel中写syscall:
- 调用save函数用来保存相关寄存器
- 调用sys_call_table [eax],即指向对应的get_ticks函数
- 然后将eax放到esi+eaxreg-p_stackbase即将上面的函数的返回值放入到进程表中
- 在proc.c中添加函数sys_get_ticks
- 在proto.h添加函数声明
- 在进程中调用相关函数
为了实现真正的时钟中断计数功能:
- 首先在global.h中定义全局变量ticks
- 在main.c中初始化
- 时钟中断处理程序中添加一个ticks++
- 让get_ticks函数返回当前ticks的值。
- 让进程打印ticks
get_ticks的应用
- 可以用来判断时间,来取代delay
- 改变时间中断的间隔
- 计数器输入频率为1193180HZ,计数器为16位的,所以最大值为65535,所以时钟中断发生频率位1193180/65535约为18.2HZ
- 为了改变时钟中断发生频率,需要修改计数器的值,即修改8253
- 首先通过端口43H来修改太复杂,这里查看其数据格式,6 7位为计数器选择位,这里要修改counter0,值应该为00,由于计数器为16位,所以高低位都要写,所以读写为即5 6 为都要为11 ,模式位为2, 所以123应该为 010 ,第0位是0,综上是00110100即0x34
- 在main,c初始化8253
- 宏定义中,HZ设为100(即发生频率为100),rate_geneator的值为0x34
- 现在中断发生时间即为10ms了
- 新的延迟函数,接受一个参数,为毫秒数,读取当前的时钟中断发生次数,然后进行一个while循环,当循环到当前中断数减去开始中断数乘以10的数字比接受参数大时,推出循环。所以会有一个的误差(即延迟函数发生时,可能马上要开始下一个时钟中断了,又因为不止一个进程在执行,所以可能发生中断重入,导致已经满足条件时切换到了其他进程,并且打印也会浪费时间)
进程调度
- 使不同的进程的延迟时间不同,这里调用上面的milli_delay函数,使进程A,B,C延迟300,900和1500ms.
- 查看输出情况
A有182个,B有63个,C有35个和BA延迟时间比3以及AC延迟时间比5基本吻合
为了实现调度算法
实现思路为:每个进程都有个新的变量,这个变量的值有大有小,进程每获得一个运行周期,就减一,直到减到0,这个进程就不再执行了,直到所有的进程都为0了,这时候再都给赋值为原来的量
现在proc.h给进程表结构体添加新成员,一个是用来递减的ticks,一个是用来恒定表示值的priority。一开始的ticks等于priority,当所有ticks都变为0时,再给他们赋值为priority.
在main.c里对其进行赋值。其中ABC的时间片分别为150 50 30
写调度算法函数:在proc.c中实现函数schedule.c函数的意义为,遍历所有进程,剩余最多时间的进程将会优先执行,当所有进程剩余时间都为0时,都重新赋值为priority。
修改时钟中断函数,将原来的直接执行下一个进程改为调用调度算法函数,并且在ticks++下面加入当前进程的ticks--
为了确保是调度算法发生的作用,这里将ABC的延迟时间都改为200
结果图
可以看到其比例大体为2.57:1.31:1,与15:5:3差别较大,为了解决这个问题
- 修改进程,让其打印当前ticks
- 修改调度算法,使其打印进程时间片
- 注释掉重新赋值的语句,以便观察
- 增加清空屏幕的函数,便于观察
- 输出结果如图
总结
- 整个执行分为三个阶段,第一个阶段,由于A的比BC的都多,所以只有A在调度,直到和B的时间一样多,即执行了100个ticks
- 第二个阶段,A和B同时被调度,直到和C一样的时候才下一阶段,因为每此只会减去一个ticks,所以执行了20*2个
- 第三阶段,ABC都被调度,这时候执行了30*3个ticks
- 所以执行时间之比应该为230:130:90即2.56:1.44.1,与上述结果大致相同
这样做,执行时间还需要计算,并不直接对应其优先级,为了方便,我们在clock_handler里加入一个判断,即只有当ticks变成0时,才转移控制权。
结果如图
第二个实验
思路,给进程表增加新的变量,当前队列,当前队列的运行时间(即时间片大小),和进程状态(0是就绪,1是运行,2是等待,3是终止)。添加进程,使得有5个进程A 、B 、C 、D、E,然后修改调度算法和时钟中断函数,使得其能够实现多级反馈队列调度算法以及进程状态的切换。具体实现如下
首先在proc.h中修该进程表,添加成员state(表示其状态),queue(表示进程所在的队列),time_remain(表示当前队列的运行时间)
这里先添加进程(
初始化时,state均为0,初始所在队列均为第一个队列,其运行时间即当前队列的时间片,由于A、B、C、D、E的运行时间分别为3,8,4,5,7,所以这里分别设其priority为15,40,20,25,35。这里的第一轮时间片是定义的一个常量,另外还有第二第三个,因为要求三个队列的时间片分别为1,2,4,所以其大小分别为5,10和20。
开始修改调度算法。
。更改时钟中断,完成时间片轮换和队列切换等
最后的实验结果截图,是符合预期的
OS第六章的更多相关文章
- 【windows核心编程】 第六章 线程基础
Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ① 一个是线程的内核 ...
- 第六章:Reminders实验:第二部分[Learn Android Studio 汉化教程]
Learn Android Studio 汉化教程 Reminders Lab: Part 2 This chapter covers capturing user input through the ...
- Spring实战第六章学习笔记————渲染Web视图
Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...
- RHCE学习笔记 管理1 (第六章 第七章)
第六章 利用linux 文件系统权限文件访问 1.linux文件系统权限 文件的权限分为: rwx 读/写/执行 ls -l /home 查看/home下文件 ls -ld /home ...
- Flask 教程 第十六章:全文搜索
本文翻译自The Flask Mega-Tutorial Part XVI: Full-Text Search 这是Flask Mega-Tutorial系列的第十六部分,我将在其中为Microblo ...
- oranges 笔记第六章
OS 第六次实验随笔 第六章6.1-6.3相关的问题 进程状态保存与恢复 哪些状态 何时保存 保存在哪 如何恢复 特权级变换 用户进程到内核 内核回到用户进程 再次理解TSS .堆栈 从外环进入内环( ...
- 【C++】《C++ Primer 》第十六章
第十六章 模板与泛型编程 面向对象编程和泛型编程都能处理在编写程序时不知道类型的情况. OOP能处理类型在程序允许之前都未知的情况. 泛型编程在编译时就可以获知类型. 一.定义模板 模板:模板是泛型编 ...
- 精通Web Analytics 2.0 (8) 第六章:使用定性数据解答”为什么“的谜团
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第六章:使用定性数据解答"为什么"的谜团 当我走进一家超市,我不希望员工会认出我或重新为我布置商店. 然而, ...
- 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章 继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章 ...
随机推荐
- IDEA主题加高亮
IntelliJ Idea的黑色主题,使用就是file-->import settings 选择压缩包里的jar包,主题就被导入了,之后会提示重启,重启完就可以在设置中使用了. IDEA主题下载 ...
- CorelDRAW常用工具之手绘工具
对于平面设计师来说,一个好用顺手的手绘工具是必不可少的,CorelDRAW的手绘工具能将手绘笔触转换成平滑的线条或者形状. 1.基础操作 CorelDRAW的手绘工具组包含手绘.2点线.贝塞尔.钢笔. ...
- mathtype样式系统使用技巧-通过样式定义来更改方程中的字体
本教程中,我们主要介绍MathType Desktop的样式系统.演示如何通过更改样式定义来更改方程中的字体.通过样式可以快速轻松地实现我们所需的公式格式,并统一所有公式的样式. 我们以如下公式来作为 ...
- Vegas教程:教你制作抖音热门人物穿越门窗特效
抖音上经常会有很多特效视频,例如换妆.分镜.合拍.放大等,合适的特效总是会让视频更加出彩.这些特效,除了一部分是抖音自带以外,很多都是用的其他视频特效软件制作而成.这些视频编辑软件操作简单易上手,强大 ...
- 自学linux——8.firewall-cmd的命令使用
firewall-cmd使用方法 1.firewall-cmd的含义 firewall-cmd 是 firewalld的字符界面管理工具,firewalld是centos7之后版本的一大特性, 最大的 ...
- 牛客练习赛66 C公因子 题解(区间gcd)
题目链接 题目大意 给你一个长为n的数组,给所有数组元素加上一个非负整数x,使得这个数组的所有元素的gcd最大 题目思路 这主要是设计到一个多个数gcd的性质 gcd(a,b,c,d.....)=gc ...
- 2020年的UWP(4)——UWP和等待Request的Desktop Extension
上一篇我们讨论了UWP和Desktop Extension交互中,Desktop Extension执行后立即退出的场景.下图是提到的四种场景分类: 执行后立即退出 等待request,处理完后退出 ...
- Cys_Control(四) MTabControl
一.查看TabControl原样式 <ControlTemplate TargetType="{x:Type TabControl}"> <Grid x:Name ...
- Django结合Websocket进行WebSSH的实现
什么是webssh? 泛指一种技术可以在网页上实现一个 终端.从而无需 之类的模拟终端工具进行 连接,将 这一比较低层的操作也从 架构扭成了 架构 这样的架构常用在运维制作开发一些堡垒机等系统中,或是 ...
- (四)CPU主频与”性能“
一.什么是性能 CPU的性能就是就是时间的倒数,简单来说:耗时越少,性能越好,主要包含下面两个指标: 响应时间:程序执行耗时 吞吐率:单位时间处理数据或执行程序的量 缩短响应时间,一定时间内可以执行更 ...