操作系统;页面置换算法;进程调度;FIFO;LRU;OPT;LFU
5.3 算法介绍与应用
5.3.1 OPT算法及数据字典
首先判断是否开启快表,假设快表开启,判断访问页号在快表中是否命中,如果快表未命中再判断物理块中是否存在,如果物理块中不存在,判断物理块是否还有剩余空间,如果内存块没用完则把该页放入物理块中,再判断快表是否用完,快表没用完的话就放入快表且快表中其他页面未被访问计时器加1,该页置1;快表用完了就遍历内存中的页面数组,分别找出他们第一次出现在laterArray[]中的索引,再遍历这些索引,找出索引最大值对应的页面就是要被淘汰的页面,再进行页面置换,访问计时器置1。如果内存块用完了且该页不是访问页面数组的最后一个,把该页后的页面重新放到另一个数组中,找到物理块所有页在laterArray[]中第一次出现的索引,如果能找到且比最大的索引还大就把这个页置换掉,如果没有找到就直接置换掉,因为它以后不会再出现。判断快表是否用完,没用完的话直接放入快表,快表中其他页面计数器时间加1;快表用完了进行快表置换,访问计数器时间置1。记录访问时间(2 * 访问快表时间 + 2 * 访问内存时间 + 缺页处理时间)。如果物理块中存在,且快表没用完将该页放入快表,快表中其他页面访问计数器加1;快表用完了则置换出最久不被访问的页号,计数器置1。记录访问时间(2 * 访问快表时间 + 2 * 访问内存时间)。快表命中则不再访问内存块,记录访问时间(访问快表时间 + 访问内存时间)。
没开启快表则判断物理块中是否存在该页,物理块中不存在的话就判断物理块是否用完,内存块没用完就把该页放入物理块中;内存块用完了进行页面置换,记录访问时间(2 * 访问内存时间 + 缺页处理时间)。物理块中存在,记录访问时间(2 * 访问内存时间)。
optblocknumlist | 物理块保存的页号的数组 |
pagelist | 保存访问页号序列的数组 |
back3 | 当前使用的物理块标号 |
blocknum | 物理块总数 |
timecounter3 | 内存中页面距离上次访问过去多久 |
d | 想要访问的页号在page数组中的下标 |
result3 | 页面访问的类型 |
displacecount3 | 页面置换次数 |
count3 | 缺页次数 |
quicktable | 是否使用快表 |
quicktable3 | 快表数组 |
quicktablenum | 快表容量 |
quicktimecounter3 | 页号在快表中距离上次访问过去多久 |
memorytime | 内存访问所需时间 |
quicktime | 快表访问所需时间 |
misstime | 缺页处理所需时间 |
accesstime3 | 访问一次页面所需时间 |
blockindex | 被置换页面 |
used3 | 查询页面是否在内存的返回值 |
exist | 查询页面是否在快表的返回值 |
5.3.2 FIFO算法及数据字典
FIFO算法的执行流程与OPT算法大体上一致,2者的区别在在置换时FIFO算法淘汰最早进入内存的页面,而OPT算法淘汰未来最久未使用的页面。当页面在内存中时,OPT算法将该页的计数值置1,并将其他页面的计数值+1,而FIFO算法不会将该页的计数值置1,而是将全部页面计数值+1,这要淘汰的时候直接选择计数值最大的页面换出内存即可。
fifoblocknumlist | 物理块保存的页号的数组 |
pagelist | 保存访问页号序列的数组 |
back2 | 当前使用的物理块标号 |
blocknum | 物理块总数 |
timecounter2 | 内存中页面距离上次访问过去多久 |
d | 想要访问的页号在page数组中的下标 |
result2 | 页面访问的类型 |
displacecount2 | 页面置换次数 |
count2 | 缺页次数 |
quicktable | 是否使用快表 |
quicktable2 | 快表数组 |
quicktablenum | 快表容量 |
quicktimecounter2 | 页号在快表中距离上次访问过去多久 |
memorytime | 内存访问所需时间 |
quicktime | 快表访问所需时间 |
misstime | 缺页处理所需时间 |
accesstime2 | 访问一次页面所需时间 |
indexOfMax2 | 被置换页面索引 |
used2 | 查询页面是否在内存的返回值 |
exist | 查询页面是否在快表的返回值 |
5.3.3 LRU算法及数据字典
LRU算法的执行流程与OPT算法大体上一致。不同的是在进行页面置换时,是将页面号访问计时器中的值最大的页面置换出去,将当前页面号加入,同时在页面号访问计时器中把当前页面号对应的时间置为1,其他页面号对应的时间+1。
lrublocknumlist | 物理块保存的页号的数组 |
pagelist | 保存访问页号序列的数组 |
back1 | 当前使用的物理块标号 |
blocknum | 物理块总数 |
timecounter | 内存中页面距离上次访问过去多久 |
d | 想要访问的页号在page数组中的下标 |
result | 页面访问的类型 |
displacecount1 | 页面置换次数 |
count1 | 缺页次数 |
quicktable | 是否使用快表 |
quicktable1 | 快表数组 |
quicktablenum | 快表容量 |
quicktimecounter1 | 页号在快表中距离上次访问过去多久 |
memorytime | 内存访问所需时间 |
quicktime | 快表访问所需时间 |
misstime | 缺页处理所需时间 |
accesstime1 | 访问一次页面所需时间 |
indexOfMax | 被置换页面索引 |
used | 查询页面是否在内存的返回值 |
exist | 查询页面是否在快表的返回值 |
5.3.4 LFU算法及数据字典
LFU算法的执行流程与OPT算法执行流程类似。LFU算法置换页面时选择淘汰访问频次最低的页面,如果访问频次最低的页面不唯一,则进一步选择LRU算法进行置换,因此在LFU算法中设置了visitcounter[]来记录每个页面被访问的频次,同时还设置了timecounter4[]作为页面的计数器。当页面被访问时,visitcounter[]的值+1,timecounter4[]的设置与在LRU算法中timecounter1[]的设置一样,在内存中存在该页面时,将该页面的timecounter1[]置1,并将其他页面的timecounter1[]+1。
lfublocknumlist | 物理块保存的页号的数组 |
allpagelist | 使用过的页面 |
pagelist | 保存访问页号序列的数组 |
back4 | 当前使用的物理块标号 |
blocknum | 物理块总数 |
timecounter4 | 内存中页面距离上次访问过去多久 |
d | 想要访问的页号在page数组中的下标 |
result4 | 页面访问的类型 |
displacecount4 | 页面置换次数 |
count4 | 缺页次数 |
quicktable | 是否使用快表 |
quicktable4 | 快表数组 |
quicktablenum | 快表容量 |
quicktimecounter4 | 页号在快表中距离上次访问过去多久 |
memorytime | 内存访问所需时间 |
quicktime | 快表访问所需时间 |
misstime | 缺页处理所需时间 |
accesstime4 | 访问一次页面所需时间 |
indexOfMax4 | 被置换页面索引 |
used4 | 查询页面是否在内存的返回值 |
exist | 查询页面是否在快表的返回值 |
5.4关键技术与主要代码
5.4.1 界面设计
网页主要由参数设置,参数显示,页面置换动态过程,历史记录四个模块组成。
- 参数设置模块包括页面设置,内存设置和快表设置。页面设置主要是设置页数,最 小页号以及最大页号。快表设置主要是快表数以及快表访问时间的设置。内存设置是对内 存块数,内存存取时间,缺页中断时间的设置。
- 参数显示模块主要显示页数,页号序列,内存块数,内存存取时间,快表数,缺页
中断时间,快表访问时间等。
(3)页面置换动态过程模块是在点击开始按钮后同时显示四种算法页面访问和置换的过程,若设置了快表,也会显示快表的访问和置换过程。页面访问的同时也会显示页号滑动的过程以及当前访问的页面。点击暂停按钮后会停止页面的访问,再次点击暂停按钮会继续访问页面,直到所有页面均访问完毕。
(4)页面访问完后,会每种算法会显示相应的缺页次数,置换次数,页面访问总时间以及缺页中断率等参数的值历史记录模块显示每次访问完整的页号序列对应的主要参数设置值,包括内存块数,页面数,内存存取时间,快表访问时间,缺页中断时间和是否启动快表。同时显示四种算法访问页号序列结束后的结果值,包括缺页次数,置换次数,缺页率和总的访问时间。
图5.1 界面展示
5.4.2 动画显示实现
data:{}中设置了全局变量,html页面中要和data中的数据绑定使用v-model即可,当data:{ }中的的数据被修改,html页面中与之绑定的数据也会实时修改,另外比如html页面中的某个input文本框的值与data:{} 中的某个数据绑定,在修改input文本框输入的时候,data:{} 中与之对应的数据也会实时修改。
created(){} 函数在页面创建的初始时刻便会执行,且只在创建的初始时刻执行,然后便不会被触发。
watch(){} 是Vue提供的监听函数,当被监听的数据值改变时,便会触发相应的函数。
methods:{} 中是项目中的方法。
以LRU算法中的内存块更新动画为例,如下图所示,其中lrublocknumlist是LRU算法中内存块中的页面号形成的数组,通过v-for循环数组创建div,数组中有多少元素,就会创建多少div,每个div中的文本就是数组中的页面号。当子线程在算法计算完成后,把数据,即lrublocknumlist,返回给主线程,主线程修改data中的lrublocknumlist即可完成动态绑定。
Vue.js可实现响应的数据绑定和组合的视图组件。在html页面引入Vue.js即可:
“ ”。本项目中对Vue框架的使用如下图所示:
图5.2 Vue框架的使用
以点击开始按钮为例,说明程序的执行过程如下:
图5.3 程序的执行过程
在HTML标签中为开始按钮绑定了相应的点击事件函数:
并且为该HTML页面指定了相应的javascript程序pagedisplace.js
图5.4 pagedisplay.js
当点击开始按钮时,会执行pagedispalce.js中的start()方法。start()方法对各个变量赋值,然后创建4个子线程同时执行LUR,FIFO,LFU,OPT算法,并接受子线程执行完成后传回来的参数。当HTML页面上相应变量的数据被修改时,vue的监听器感知到后会执行相应的程序改变HTML界面中展示部分的样式和内容,从而达到动画的效果。
5.4.3历史记录查看
点击历史记录时将会跳转到另一个html页面,当在页面创建的时候触发Vue中的created( )函数,执行created( )函数将会从本地存储中取出保存的记录,并修改data全局变量中的对应的值即可完成显示。
对每次执行结果进行记录,且记录可以查询,本项目中使用了HTML5的本地存储,即Local Storage, web应用程序能够在用户浏览器中对数据进行本地的存储。localStorage对象存储的是没有截止日期的数据。当浏览器被关闭时数据不会被删除,在下一天、周或年中,都是可用的。
localStorage.setItem(“records", “hello”):对记录存储或者更新,其中“records”是关键字,“hello”是与关键字对应的值,如果本地存储中已经保存有了“records”关键字,则值“hello”会把原值覆盖掉。
localStorage.getItem(“records”):将记录取出,如果本地存储中没有“records”关键字则结果为空,即null。
JSON.stringify():将JSON转化为字符串。本项目中在每次运行完成的时候将会收集本次的运行的数据结果,生成一条记录,自动存储或更新到本地存储中. localStorage存储时限定类
型为字符串,所以本项目中把所要存储的信息封装成一个JSON格式的数据,在存储时图
将JSON转化为字符串进行存储,如图所示:
5.5 历史记录查看相关代码
JSON.parse():将字符串解析为JSON。在取出时,将字符串再次转化为JSON格式的数据,数据如下图所示:
图5.6 数据格式转换
5.4.4产生随机页面号序列
产生随机页面号序列时可以指定页面号的最大值和最小值,以及页面号的个数,JavaScript中产生随机数可使用Math.random( ),将会产生大于等于0、小于1的小数,本项目中需要产生大于等于指定的最小页号、小于等于指定的最大页号,可利用下面的函数达到目的。
randomNum : function ( minNum, maxNum ) {
let range = maxNum - minNum
let rand = Math.random( )
return minNum + Math.round(rand*range)
}
产生完整的随机页面号序列,如下面程序所示:
for ( let i = 0; i < this.pagesnum; i++ ) {
let r = this.randomNum(parseInt( this.minpagenum ), parseInt( this.maxpagenum ))
this.pagelist.push(r)}
下载地址:页面置换算法下载