分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,从0开始,如第0页、第1页等。相应地,也把内存空间分成与页面相同大小的若干个存储块,称为(物理)块或页框(frame),也同样为它们加以编号,如0#块、1#块等等。在为进程分配内存时,以块为单位将进程中的若干个页分别装入到多个可以不相邻接的物理块中。虚拟内存的作用内存在计算机中的作用很大,电脑中所有运行的程序都需要经过内存来执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,Windows中运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张。请求分页虚拟存储系统是将作业信息的副本存放在磁盘这一类辅助存储器中,当作业被调度投入运行时,并不把作业的程序和数据全部装入主存,而仅仅装入立即使用的那些页面,至少要将作业的第一页信息装入主存,在执行过程中访问到不在主存的页面时,再把它们动态地装入。而替换规则用来确定替换主存中哪一部分,以便腾空部分主存,存放来自辅存要调入的那部分内容。
目录
1 项目描述与分析报告
1.1 任务概述
本次课程设计采用一些常用的存储器分配算法,设计一个请求页式存储管理模拟系统并调试运行。通过随机数产生一个指令序列,将指令序列变成为页地址流,计算并输出下述各种算法在不同内存容量下的命中率。
1.2 设计环境
(1) 硬件:PC机,要求能运行Windows XP、Windows7或Windows 10操作系统。
(2) 软件:
·操作系统:Windows系列。
·程序设计语言:C
1.3 需求分析
首先我们需要通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成(可选,也可随机产生):
①50%的指令是顺序执行的;
②25%的指令是均匀分布在前地址部分;
③25%的指令是均匀分布在后地址部分。
在生成指令序列之后我们需要将指令序列变成为页地址流,设:
①页面大小为1k;
②用户内存容量为4页到32页;
③用户虚量容量为32k。
在用户虚存中,按每k存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:
第0条~第9条指令为第0页(对应虚存地址为[0,9]);
第10条~第19条指令为第1页(对应虚存地址为[10,19]);
……
第310条~第319条指令为第31页(对应虚存地址为[310,319]);
按以上方式,用户指令可组成32页。
根据访问的页数生成访问串,然后我们需要编写和执行不同的页替换策略算法(FIFO先进先出页面替换策略、OPT最佳页面替换策略、LRU最近最少用页面替换策略、CLOCK时钟页面替换策略),并计算并输出下述各种算法在不同内存容量下的命中率。
2 项目设计与实现报告
2.1 系统设计思想
为了使用在需求分析中指定的原则,通过随机数产生一个指令序列,共320条指令。具体的实施方法是:
①在[0,319]的指令地址之间随机选取一起点m;
②顺序执行一条指令,即执行地址为m+1的指令;
③在前地址[0,m+1]中随机选取一条指令并执行,该指令地址为m’;
④顺序执行一条指令,其地址为m’+1;
⑤在后地址[m’+2,319]中随机选取一条指令并执行;
⑥重复上述步骤①~⑤,直到执行320次指令。
关于随机数产生法,系统提供函数srand()和rand(),分别进行初始化和产生随机数。
然后创建存储指令序列的结构体,存放生成的指令序列和指令所在页号,以便于之后通过页号的访问串来执行页替换策略算法。
接下来我们要创建结构体数组记录放在主存中的页的一些信息,即驻留集。为了实现LRU策略我们需要增加计数器,为了实现CLOCK策略我们需要增加访问位。因此内存块结构体成员包括页面号、计数器、访问位。
在用户通过随机数产生了指令序列之后,也相应生成了对应页面号的访问串,这时候用户可以选择测试不同页替换策略算法的缺页数和命中率。
FIFO先进先出页面替换策略替换最早进入的页;OPT最佳页面替换策略淘汰下次访问距当前最远的那些页中序号最小的页;LRU最近最少用页面替换策略通过计数器淘汰上次使用距当前最远的页;CLOCK时钟页面替换策略基于LRU的思想,硬件在页面被访问时设置页表项中的访问位,随着表针的移动,淘汰访问位是0的页面,或清除页面的访问位。
基于上述策略的特点设计好程序算法。
最后,计算并输出下述各种算法在不同内存容量下的命中率。在本次课程设计中,页地址长度为320,页面失效次数为每次访问相应指令时,该指令所对应的页不内存的次数。
2.2 系统整体功能图
2.3 随机生成指令集
首先通过srand()函数初始化种子,再依照之前需求分析和系统设计所要求的原则来生成随机数并且存入指令序列结构体数组中,在存入指令地址的同时计算并存入页面号和偏移。需要注意的是需要判断m和m’是否为319,如果为319则m+1或m’+1会引起指令越界。
关键代码:
1. void initcount(){
2. int flag=0;
3. srand((unsigned)time(NULL));//根据系统时间产生随机数
4. for(int i=0;i<ordernum;i+=4){
5. int rands=rand()%ordernum;//0-319中选一点
6. if(rands==ordernum-1){
7. printf("指令即将越界!\n");
8. flag=1;
9. }
10. o[i].order=rands+1;//执行m+1指令
11. o[i+1].order=rand()%(o[i].order+1);//在[0,m+1]选择执行m'
12. if(o[i+1].order==ordernum-1){
13. printf("指令即将越界!\n");
14. flag=1;
15. }
16. o[i+2].order=o[i+1].order+1; // 执行m'+1
17. o[i+3].order=rand()%(ordernum-o[i+2].order-1)+o[i+2].order+1;//在[m'+2,319]执行
18. }
19. for(int i=0;i<ordernum;i++){
20. o[i].page=o[i].order/pageordermax;
21. o[i].offset=o[i].order%pageordermax;
22. }
23. if(flag!=1)
24. printf("随机指令集生成成功!\n");
25. }
运行结果如图所示,指令列为随机生成的指令的指令地址,页面号为指令所在的页面号,偏移是指指令在页面的偏移量。这些信息都存储在指令序列的结构体数组之中,之后执行页替换策略算法时,即使用结构体数组之中的数据。