分页存储管理的模拟实验上机报告
虚拟页面管理实验报告(3篇)
第1篇一、实验目的1. 理解虚拟存储器的概念和作用。
2. 掌握分页式存储管理的基本原理和地址转换过程。
3. 熟悉几种常见的页面置换算法,并比较其优缺点。
4. 通过实验,加深对虚拟存储器管理机制的理解。
二、实验内容1. 模拟分页式存储管理中的地址转换过程。
2. 比较几种常见的页面置换算法:FIFO、LRU、LFU和OPT。
三、实验原理虚拟存储器是一种将内存和磁盘结合使用的存储管理技术,它允许程序使用比实际物理内存更大的地址空间。
虚拟存储器通过将内存划分为固定大小的页(Page)和相应的页表(Page Table)来实现。
1. 分页式存储管理分页式存储管理将内存划分为固定大小的页,每个页的大小相同。
程序在运行时,按照页为单位进行内存访问。
分页式存储管理的主要优点是内存碎片化程度低,便于实现虚拟存储器。
2. 页面置换算法当内存中没有足够的空间来存放新请求的页面时,需要将某个页面从内存中移除,这个过程称为页面置换。
以下介绍几种常见的页面置换算法:(1)FIFO(先进先出):优先淘汰最早进入内存的页面。
(2)LRU(最近最少使用):优先淘汰最近最少被访问的页面。
(3)LFU(最不频繁使用):优先淘汰最不频繁被访问的页面。
(4)OPT(最佳置换):优先淘汰未来最长时间内不再被访问的页面。
四、实验步骤1. 模拟分页式存储管理中的地址转换过程(1)创建一个模拟内存的数组,表示物理内存。
(2)创建一个模拟页表的数组,用于存放虚拟页号和物理页号之间的映射关系。
(3)模拟进程对内存的访问,将访问的虚拟页号转换为物理页号。
2. 比较几种常见的页面置换算法(1)创建一个模拟进程的数组,包含访问的虚拟页号序列。
(2)对每个页面置换算法,模拟进程的运行过程,记录缺页中断次数。
(3)计算不同页面置换算法的缺页率,并比较其性能。
五、实验结果与分析1. 分页式存储管理中的地址转换过程实验结果表明,分页式存储管理能够有效地将虚拟地址转换为物理地址,实现虚拟存储器。
分页氏存储管理实验报告
分页存储管理实验报告姓名:何绍金班级:自动化1202学号:201203870408指导教师:张健2014年12月30日一.实验题目编写程序模拟操作系统的基本分页存储管理方式,进一步理解这种内存分配方式的原理和特点,加深对理论知识的掌握。
二. 实验内容1.实验要求(1)编写模拟操作系统对内存分页存储管理方式的程序。
(2)程序能正确对主存空间进行“分配”和“回收”。
(3)能接受用户的输入,显示内存的分配情况,并有一定的容错能力。
2.实现功能:(1)内存初始化(2)程序应该能接受用户输入的进程信息,并为之分配内存,返回分配结果注意:此处考虑到不合法的输入并进行相应处理。
(3)程序能回收用户指定的进程所占用的内存空间程序需要为每个进程分配一个唯一的进程号并给出详细的提示信息。
(4)能直观合理地显示内存分配情况三.实验流程图四.程序运行结果运行程序得到如下结果:五.实验小结这次实验让我清楚地认识到分页存储管理的基本原理和实现流程,特别是对主存空间的分配与回收的深层次理解,在编制程序是只需使用顺序的地址而不必去考虑如何去分页,因为分页存储管理时作业的地址是连续的。
更让我体会了页氏存储管理方式的优点就是没有外部碎片,程序不必连续存放在内存空间,而缺点是程序要全部装入内存。
此外,还增强了动手编程和分析解决问题的能力。
附:程序源代码按流程图编制的源代码如下所示:#include <stdio.h>#include <windows.h>#define N 100 // 共有100个内存块int process[N][N+1]; // 存放每个进程的页表int block[N]; // 内存块状态标志数组,0:空闲,1:使用int blockCount; // 记录当前内存剩余空间int processCount; // 记录当前进程数bool flag = true;void init();void output();bool createProcess();bool endProcess();void init(){int i, j;// 初始化内存状态标志数组for (i=0; i<N; i++)block[i] = 0;for (i=0; i<20; i++)block[rand()%(N-1)] = 1;blockCount = 0;for (i=0; i<N; i++)if (block[i] == 0)blockCount++;// 初始化存放进程的数组for (i=0; i<N; i++){process[i][0] = 0;for (j=1; j<N; j++)process[i][j] = -1;}processCount = 0;printf("初始化结果如下:");output();flag = false;}void output(){printf("\n内存总量:%d 块, 已用空间:%d 块, 剩余空间:%d 块, 进程总数:%d 个\n", N, N-blockCount, blockCount, processCount);if (flag && blockCount < N){printf("已使用的内存块(%d):\n", N-blockCount);for (int k=0,count=0; k<N; k++){if (block[k] == 1)printf("%2d ", k, ++count);if (count == 15){putchar('\n');count = 0;}}putchar('\n');}// 输出各进程占用内存详细情况if (processCount > 0){printf("内存详细使用情况如下:\n");for (int i=0; i<N; i++){if (process[i][0] > 0){printf("进程号:%d \n占用内存块(%2d):", i, process[i][0]);for (int j=1,count=0; j<=process[i][0]; j++){printf("%2d ", process[i][j], count++);if (count == 15){putchar('\n');printf(" ");count = 0;}}putchar('\n');}}}elseprintf("当前内存无进程!\n");/*// 输出空闲内存块if (blockCount > 0){printf("空闲内存块(%d):\n", blockCount);for (int k=0,count=0; k<N; k++){if (block[k] == 0)printf("%2d ", k, ++count);if (count == 15){putchar('\n');count = 0;}}putchar('\n');}*/putchar('\n');}bool createProcess(){int pid, pages, k = 0;loop:printf("请输入进程号(小于%d)和所需页面数:", N);scanf("%d%d", &pid, &pages);if (pid > 99){printf("错误!进程号过大!\n");goto loop;}if (pages > blockCount)return false;blockCount -= pages;process[pid][0] = pages;for (int i=1; i<=pages; i++){while (block[k]==1 && k<100)k++;process[pid][i] = k;block[k] = 1;k++;}processCount++;return true;}bool endProcess(){int pid, pages;if (processCount < 1){printf("当前内存没有进程!\n\n");return false;}printf("当前内存中的进程有 %d 个,进程号为:", processCount);for (int i=0; i<N; i++)if (process[i][0] > 0)printf("%2d ", i);putchar('\n');printf("请输入您要结束的进程号(小于%d):", N);scanf("%d", &pid);pages = process[pid][0];if (pages == 0){printf("对不起!该进程不存在!\n");return false;}for (int j=1; j<pages; j++){block[process[pid][j]] = 0;process[pid][j] = -1;}process[pid][0] = 0;processCount--;blockCount += pages;return true;}void menu(){int choice;while (true){printf("操作菜单:\n");printf(" 1 --> 创建进程\n 2 --> 结束进程\n 3 --> 查看内存\n 0 --> 退出程序\n");printf("请输入您要进行的操作:");scanf("%d", &choice);switch (choice){case 1:if (createProcess())printf("创建新进程成功!\n\n");elseprintf("抱歉!内存空间不足,创建新进程失败!\n\n");break;case 2:if (endProcess())printf("进程已结束!\n\n");elseprintf("进程结束失败!\n\n");break;case 3:output();break;case 0:return ;default:printf("对不起!您的选择有误!请重新选择!\n\n");}}}void main(){init();menu();}。
操作系统实验4-请求分页存储管理模拟实验
实验四请求分页存储管理模拟实验一:实验目得通过对页面、页表、地址转换与页面置换过程得模拟,加深对请求分页存储管理系统得原理与实现技术得理解.二:实验内容假设每个页面可以存放10条指令,分配给进程得存储块数为4。
用C语言或Pascal语言模拟一进程得执行过程。
设该进程共有320条指令,地址空间为32个页面,运行前所有页面均没有调入内存。
模拟运行时,如果所访问得指令已经在内存,则显示其物理地址,并转下一条指令;如果所访问得指令还未装入内存,则发生缺页,此时需要记录缺页产生次数,并将相应页面调入内存,如果4个内存块已满,则需要进行页面置换。
最后显示其物理地址,并转下一条指令。
在所有指令执行完毕后,显示进程运行过程中得缺页次数与缺页率.页面置换算法:分别采用OPT、FIFO、LRU三种算法。
进程中得指令访问次序按如下原则生成:50%得指令就是顺序执行得。
25%得指令就是均匀分布在低地址部分.25%得指令就是均匀分布在高地址部分.三:实验类别分页存储管理四:实验类型模拟实验五:主要仪器计算机六:结果OPT:LRU:FIFO:七:程序# i nclude 〈stdio 、h 〉# incl ude 〈stdlib 、h 〉# include 〈conio 、h># def ine blockn um 4//页面尺寸大小int m; //程序计数器,用来记录按次序执行得指令对应得页号s ta ti c in t num [320]; //用来存储320条指令typedef s truct BLOCK //声明一种新类型—-物理块类型{ﻩint pagenum; //页号ﻩint acces sed; //访问量,其值表示多久未被访问}BLOCK ;BLOCK bl ock [bl ocknum ]; //定义一大小为8得物理块数组void init () //程序初始化函数,对bl ock 初始化{for (int i=0;i <blo cknum;i++)block[i]、pagenum=—1;block[i]、accessed=0;ﻩm=0;}}int pageExist(int curpage)//查找物理块中页面就是否存在,寻找该页面curpage就是否在内存块block中,若在,返回块号{ﻩfor(int i=0;i<blocknum; i++)ﻩ{ﻩﻩif(block[i]、pagenum == curpage )ﻩﻩreturn i; //在内存块block中,返回块号ﻩ}return -1;}int findSpace()//查找就是否有空闲物理块,寻找空闲块block,返回其块号{for(int i=0;i<blocknum;i++)ﻩ{if(block[i]、pagenum==-1)ﻩreturn i;//找到了空闲得block,返回块号}ﻩreturn -1;}int findReplace()//查找应予置换得页面{ﻩint pos = 0;ﻩfor(int i=0;i〈blocknum;i++){if(block[i]、accessed 〉block[pos]、accessed)ﻩpos = i; //找到应该置换页面,返回BLOCK中位置ﻩ}return pos;}void display()//显示物理块中得页面号{ﻩﻩfor(int i=0; i〈blocknum; i++)ﻩ{ﻩif(block[i]、pagenum != -1)ﻩ{ﻩﻩprintf(” %02d ",block[i]、pagenum);ﻩﻩﻩprintf("%p |”,&block[i]、pagenum);ﻩﻩ}printf("\n");}void randam()//产生320条随机数,显示并存储到num[320]{int flag=0;printf(”请为一进程输入起始执行指令得序号(0~320):\n”);ﻩscanf("%d",&m);//用户决定得起始执行指令printf("******进程中指令访问次序如下:(由随机数产生)*******\n");for(int i=0;i〈320;i++){//进程中得320条指令访问次序得生成ﻩﻩnum[i]=m;//当前执行得指令数,ﻩﻩif(flag%2==0)ﻩm=++m%320;//顺序执行下一条指令ﻩﻩif(flag==1)ﻩﻩm=rand()%(m-1);//通过随机数,跳转到低地址部分[0,m—1]得一条指令处,设其序号为m1if(flag==3)ﻩﻩm=m+1+(rand()%(320-(m+1)));//通过随机数,跳转到高地址部分[m1+2,319]得一条指令处,设其序号为m2ﻩﻩflag=++flag%4;ﻩprintf(” %03d”,num[i]);//输出格式:3位数ﻩﻩif((i+1)%10==0)//控制换行,每个页面可以存放10条指令,共32个页面ﻩprintf(”\n”);}}void pagestring() //显示调用得页面序列,求出此进程按次序执行得各指令所在得页面号并显示输出{for(int i=0;i〈320;i++)ﻩ{printf(”%02d",num[i]/10);//输出格式:2位数if((i+1)%10==0)//控制换行,每个页面可以存放10条指令,共32个页面ﻩﻩprintf("\n”);}}void OPT() //最佳替换算法{ﻩint n=0;//记录缺页次数int exist,space,position;ﻩintcurpage;//当前指令得页面号ﻩfor(int i=0;i<320;i++)ﻩ{ﻩm=num[i];ﻩcurpage=m/10;ﻩﻩexist=pageExist(curpage);ﻩif(exist==-1)ﻩﻩ{ //当前指令得页面号不在物理块中space=findSpace();ﻩﻩif(space != -1)ﻩﻩ{//当前存在空闲得物理块ﻩﻩblock[space]、pagenum= curpage;//将此页面调入内存ﻩﻩﻩdisplay();//显示物理块中得页面号ﻩﻩn++;//缺页次数+1ﻩ}ﻩﻩelseﻩﻩ{ //当前不存在空闲得物理块,需要进行页面置换for(intk=0;k<blocknum;k++)ﻩﻩﻩﻩ{for(int j=i;j〈320;j++)ﻩ{//找到在最长(未来)时间内不再被访问得页面ﻩﻩﻩﻩif(block[k]、pagenum!= num[j]/10)ﻩﻩﻩ{ﻩﻩblock[k]、accessed = 1000;ﻩﻩﻩ} //将来不会被访问,设置为一个很大数ﻩﻩﻩelseﻩﻩﻩ{ //将来会被访问,访问量设为jﻩﻩﻩblock[k]、accessed = j;ﻩﻩﻩﻩﻩbreak;ﻩﻩﻩﻩ}ﻩﻩﻩ}ﻩ}ﻩposition = findReplace();//找到被置换得页面,淘汰ﻩblock[position]、pagenum = curpage;// 将新页面调入display();ﻩﻩn++; //缺页次数+1ﻩ}}ﻩ}ﻩprintf(”缺页次数:%d\n",n);printf("缺页率:%f%%\n",(n/320、0)*100);}void LRU() //最近最久未使用算法{int n=0;//记录缺页次数ﻩint exist,space,position ;ﻩint curpage;//当前指令得页面号ﻩfor(int i=0;i<320;i++)ﻩ{ﻩm=num[i];ﻩﻩcurpage=m/10;ﻩexist = pageExist(curpage);ﻩif(exist==-1)ﻩﻩ{ //当前指令得页面号不在物理块中space = findSpace();ﻩﻩif(space!= —1)ﻩ{ //当前存在空闲得物理块ﻩﻩblock[space]、pagenum = curpage;//将此页面调入内存ﻩﻩdisplay();//显示物理块中得页面号ﻩn++;//缺页次数+1ﻩﻩ}else{ //当前不存在空闲得物理块,需要进行页面置换ﻩﻩposition= findReplace();ﻩblock[position]、pagenum = curpage;ﻩﻩdisplay();ﻩn++;//缺页次数+1ﻩ}ﻩﻩ}elseﻩﻩblock[exist]、accessed = -1;//恢复存在得并刚访问过得BLOCK中页面accessed为-1for(int j=0; j<blocknum; j++)ﻩﻩ{//其余得accessed++ﻩﻩblock[j]、accessed++;}ﻩ}printf("缺页次数:%d\n”,n);ﻩprintf("缺页率:%f%%\n",(n/320、0)*100);}void FIFO(){int n=0;//记录缺页次数int exist,space,position ;ﻩ int curpage;//当前指令得页面号int blockpointer=-1;for(int i=0;i<320;i++)ﻩ{ﻩ m=num[i];curpage=m/10;ﻩexist = pageExist(curpage);ﻩ if(exist==-1){//当前指令得页面号不在物理块中ﻩ space = findSpace();ﻩﻩif(space !=-1)ﻩ { //当前存在空闲得物理块ﻩﻩ blockpointer++;ﻩﻩﻩblock[space]、pagenum=curpage; //将此页面调入内存ﻩ n++;//缺页次数+1ﻩﻩﻩ display();//显示物理块中得页面号ﻩ}ﻩ elseﻩ { //没有空闲物理块,进行置换ﻩﻩﻩﻩposition = (++blockpointer)%4;ﻩ block[position]、pagenum = curpage;//将此页面调入内存ﻩﻩn++;ﻩﻩ display();ﻩ}ﻩ }}printf("缺页次数:%d\n",n);printf("缺页率:%f%%\n",(n/320、0)*100);}void main(){ﻩint choice;ﻩprintf("************请求分页存储管理模拟系统*************\n");ﻩrandam();printf("************此进程得页面调用序列如下**************\n”);pagestring();ﻩwhile(choice!= 4){ﻩﻩprintf("********1:OPT 2:LRU 3:FIFO 4:退出*********\n”);ﻩprintf("请选择一种页面置换算法:”);ﻩscanf("%d",&choice);ﻩinit();ﻩswitch(choice)ﻩ{ﻩcase 1:ﻩﻩﻩprintf(”最佳置换算法OPT:\n");ﻩprintf("页面号物理地址页面号物理地址页面号物理地址页面号物理地址\n");ﻩﻩﻩOPT();ﻩbreak;ﻩcase 2:ﻩﻩprintf("最近最久未使用置换算法LRU:\n");ﻩprintf("页面号物理地址页面号物理地址页面号物理地址页面号物理地址\n");ﻩLRU();ﻩﻩﻩbreak;ﻩﻩcase 3:ﻩprintf("先进先出置换算法FIFO:\n");ﻩprintf("页面号物理地址页面号物理地址页面号物理地址页面号物理地址\n");FIFO();ﻩﻩbreak;ﻩ}}}。
操作系统实验4-请求分页存储管理模拟实验
实验四请求分页存储管理模拟实验一:实验目的通过对页面、页表、地址转换和页面置换过程的模拟,加深对请求分页存储管理系统的原理和实现技术的理解。
二:实验内容假设每个页面可以存放10条指令,分配给进程的存储块数为4。
用C语言或Pascal语言模拟一进程的执行过程。
设该进程共有320条指令,地址空间为32个页面,运行前所有页面均没有调入内存。
模拟运行时,如果所访问的指令已经在内存,则显示其物理地址,并转下一条指令;如果所访问的指令还未装入内存,则发生缺页,此时需要记录缺页产生次数,并将相应页面调入内存,如果4个内存块已满,则需要进行页面置换。
最后显示其物理地址,并转下一条指令。
在所有指令执行完毕后,显示进程运行过程中的缺页次数和缺页率。
页面置换算法:分别采用OPT、FIFO、LRU三种算法。
进程中的指令访问次序按如下原则生成:50%的指令是顺序执行的。
25%的指令是均匀分布在低地址部分。
25%的指令是均匀分布在高地址部分。
三:实验类别分页存储管理四:实验类型模拟实验五:主要仪器计算机六:结果OPT:LRU:FIFO:七:程序# include<stdio.h># include<stdlib.h># include<conio.h># define blocknum 4//页面尺寸大小int m; //程序计数器,用来记录按次序执行的指令对应的页号static int num[320]; //用来存储320条指令typedef struct BLOCK //声明一种新类型--物理块类型{int pagenum; //页号int accessed; //访问量,其值表示多久未被访问}BLOCK;BLOCK block[blocknum]; //定义一大小为8的物理块数组void init() //程序初始化函数,对block初始化{for(int i=0;i<blocknum;i++){block[i].pagenum=-1;block[i].accessed=0;m=0;}}int pageExist(int curpage)//查找物理块中页面是否存在,寻找该页面curpage是否在内存块block中,若在,返回块号{for(int i=0; i<blocknum; i++){if(block[i].pagenum == curpage )return i; //在内存块block中,返回块号}return -1;}int findSpace()//查找是否有空闲物理块,寻找空闲块block,返回其块号{for(int i=0;i<blocknum;i++){if(block[i].pagenum==-1)return i; //找到了空闲的block,返回块号}return -1;}int findReplace()//查找应予置换的页面{int pos = 0;for(int i=0;i<blocknum;i++){if(block[i].accessed > block[pos].accessed)pos = i; //找到应该置换页面,返回BLOCK中位置}return pos;void display()//显示物理块中的页面号{for(int i=0; i<blocknum; i++){if(block[i].pagenum != -1){printf(" %02d ",block[i].pagenum);printf("%p |",&block[i].pagenum);}}printf("\n");}void randam()//产生320条随机数,显示并存储到num[320]{int flag=0;printf("请为一进程输入起始执行指令的序号(0~320):\n");scanf("%d",&m);//用户决定的起始执行指令printf("******进程中指令访问次序如下:(由随机数产生)*******\n");for(int i=0;i<320;i++){//进程中的320条指令访问次序的生成num[i]=m;//当前执行的指令数,if(flag%2==0)m=++m%320;//顺序执行下一条指令if(flag==1)m=rand()%(m-1);//通过随机数,跳转到低地址部分[0,m-1]的一条指令处,设其序号为m1if(flag==3)m=m+1+(rand()%(320-(m+1)));//通过随机数,跳转到高地址部分[m1+2,319]的一条指令处,设其序号为m2flag=++flag%4;printf(" %03d",num[i]);//输出格式:3位数if((i+1)%10==0) //控制换行,每个页面可以存放10条指令,共32个页面printf("\n");}}void pagestring() //显示调用的页面序列,求出此进程按次序执行的各指令所在的页面号并显示输出{for(int i=0;i<320;i++){printf(" %02d",num[i]/10);//输出格式:2位数if((i+1)%10==0)//控制换行,每个页面可以存放10条指令,共32个页面printf("\n");}}void OPT() //最佳替换算法{int n=0;//记录缺页次数int exist,space,position;int curpage;//当前指令的页面号for(int i=0;i<320;i++){m=num[i];curpage=m/10;exist=pageExist(curpage);if(exist==-1){ //当前指令的页面号不在物理块中space=findSpace();if(space != -1){ //当前存在空闲的物理块block[space].pagenum = curpage; //将此页面调入内存display();//显示物理块中的页面号n++;//缺页次数+1}else{ //当前不存在空闲的物理块,需要进行页面置换for(int k=0;k<blocknum;k++){for(int j=i;j<320;j++){//找到在最长(未来)时间内不再被访问的页面if(block[k].pagenum!= num[j]/10){block[k].accessed = 1000;} //将来不会被访问,设置为一个很大数else{ //将来会被访问,访问量设为jblock[k].accessed = j;break;}}}position = findReplace();//找到被置换的页面 ,淘汰block[position].pagenum = curpage;// 将新页面调入display();n++; //缺页次数+1}}}printf("缺页次数:%d\n",n);printf("缺页率:%f%%\n",(n/320.0)*100);}void LRU() //最近最久未使用算法{int n=0;//记录缺页次数int exist,space,position ;int curpage;//当前指令的页面号for(int i=0;i<320;i++){m=num[i];curpage=m/10;exist = pageExist(curpage);if(exist==-1){ //当前指令的页面号不在物理块中space = findSpace();if(space != -1){ //当前存在空闲的物理块block[space].pagenum = curpage; //将此页面调入内存display();//显示物理块中的页面号n++;//缺页次数+1}else{ //当前不存在空闲的物理块,需要进行页面置换position = findReplace();block[position].pagenum = curpage;display();n++; //缺页次数+1}}elseblock[exist].accessed = -1;//恢复存在的并刚访问过的BLOCK中页面accessed为-1for(int j=0; j<blocknum; j++){//其余的accessed++block[j].accessed++;}}printf("缺页次数:%d\n",n);printf("缺页率:%f%%\n",(n/320.0)*100);}void FIFO(){int n=0;//记录缺页次数int exist,space,position ;int curpage;//当前指令的页面号int blockpointer=-1;for(int i=0;i<320;i++){m=num[i];curpage=m/10;exist = pageExist(curpage);if(exist==-1){ //当前指令的页面号不在物理块中space = findSpace();if(space != -1){ //当前存在空闲的物理块blockpointer++;block[space].pagenum=curpage; //将此页面调入内存n++;//缺页次数+1display();//显示物理块中的页面号}else{ // 没有空闲物理块,进行置换position = (++blockpointer)%4;block[position].pagenum = curpage; //将此页面调入内存n++;display();}}}printf("缺页次数:%d\n",n);printf("缺页率:%f%%\n",(n/320.0)*100);}void main(){int choice;printf("************请求分页存储管理模拟系统*************\n");randam();printf("************此进程的页面调用序列如下**************\n");pagestring();while(choice != 4){printf("********1:OPT 2:LRU 3:FIFO 4:退出*********\n");printf("请选择一种页面置换算法:");scanf("%d",&choice);init();switch(choice){case 1:printf("最佳置换算法OPT:\n");printf("页面号物理地址页面号物理地址页面号物理地址页面号物理地址\n");OPT();break;case 2:printf("最近最久未使用置换算法LRU:\n");printf("页面号物理地址页面号物理地址页面号物理地址页面号物理地址\n");LRU();break;case 3:printf("先进先出置换算法FIFO:\n");printf("页面号物理地址页面号物理地址页面号物理地址页面号物理地址\n");FIFO();break;}}}。
基本分页存储管理的模拟实现
基本分页存储管理的模拟实现学院:专业:学生姓名:学号:指导教师:2014年3月 18 日目录一、设计内容 (2)二、相关操作系统的知识介绍 (2)三、课程设计的目的及要求 (2)四、程序功能说明 (3)五、算法整体思想 (3)六、主要功能模块进程图 (3)七、实验结果 (4)八、实验总结 (7)九、程序代码 (7)一、设计内容根据设计要求实现对基本分页存储管理的模拟二、相关操作系统的知识介绍连续分配方式会形成许多“碎片”,虽然可通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大的开销。
如果允许将一个进程直接分散的装入到许多不相邻接的分区中,则无需在进行“紧凑”。
基于这一思想而产生了离散分配方式。
如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。
在分页存储管理方式中,如果不具备页面对换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具有支持实现虚拟存储的功能,它要求把每个作业全部装入内存后方能运行。
三、课程设计的目的及要求1、课程设计的目的操作系统课程设计是计算机专业重要的教学环节,它为我们提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决实际问题的机会。
●进一步巩固和复习操作系统的基础知识。
●培养我们结构化程序、模块化程序设计的方法和能力。
●提高我们调试程序的技巧和软件设计的能力。
●提高我们分析问题、解决问题以及综合利用 C 语言进行程序设计的能力。
2、设计要求1.选择恰当的数据结构表示页表2.进程名,进程所需页数,进程进行的操作(装入/退出)等操作可有键盘输入,也可从文件读出。
3.每进行一次进程的装入或者退出操作,就显示出操作执行后内存中各页的分配情况。
四、程序功能说明函数各模块部分功能void CreatA()//创建内存新函数void NewNode(LinkList &L)//建立新进程void FreeNode(LinkList &L)//回收进程,释放内存void Printf(LinkList L)//显示所有进程所占物理块信息void look(LinkList L)//查看进程信息void showit()//显示内存块使用信息函数的整体功能这个程序是为了实现离散分配方式,以消减内存的外零头,提高内存的利用率,由系统把逻辑地址划分为页号和页内地址两部分。
分区存储管理的实验报告
分区存储管理的实验报告分区存储管理的实验报告引言:分区存储管理是操作系统中重要的一部分,它负责将计算机的内存划分成若干个区域,每个区域可用于存储不同的数据和程序。
本实验旨在通过模拟分区存储管理的过程,了解不同的分区算法以及它们对系统性能的影响。
实验过程:1. 实验环境准备在实验开始前,我们需要准备一个模拟的操作系统环境。
为了方便起见,我们选择了一款名为"OS Simulator"的软件,它能够模拟出一个具有分区存储管理功能的操作系统。
2. 分区算法的选择在实验中,我们选择了三种常见的分区算法,包括首次适应算法、最佳适应算法和最坏适应算法。
首次适应算法会在内存中找到第一个能够容纳所需大小的空闲区域进行分配;最佳适应算法会在内存中找到能够最小程度浪费空间的空闲区域进行分配;最坏适应算法则相反,会选择能够最大程度浪费空间的空闲区域进行分配。
3. 实验设计我们设计了一系列的实验来比较不同的分区算法对系统性能的影响。
首先,我们随机生成了一批不同大小的作业,并将它们按照不同的分区算法分配到内存中。
然后,我们记录下每个作业分配的时间、分配的分区大小以及内存中的碎片情况。
4. 实验结果与分析通过对实验数据的分析,我们得出了以下结论:- 首次适应算法的优点是分配速度快,但由于它会在内存中留下许多小碎片,导致内存利用率较低。
- 最佳适应算法虽然能够尽量减少碎片,但由于需要搜索整个内存空间,分配速度较慢。
- 最坏适应算法在减少碎片方面表现较差,但它能够快速找到足够大的空闲区域进行分配。
结论:通过本次实验,我们深入了解了分区存储管理的原理和常见的分区算法。
不同的分区算法在性能上有着各自的优劣势,选择合适的算法需要根据具体的应用场景和需求来决定。
此外,我们还发现分区存储管理对于系统性能的影响十分重要,合理地管理内存空间能够提高系统的运行效率和资源利用率。
展望:虽然本实验只是对分区存储管理的一次模拟实验,但我们相信通过这次实验的学习和理解,我们能够更好地理解操作系统中的分区存储管理。
分页存储实验报告
分页存储实验报告分页存储实验报告一、引言分页存储是计算机系统中一种常见的内存管理技术。
它将主存分成固定大小的页框,并将进程的地址空间划分为相同大小的页面。
本实验旨在通过设计和实现一个简单的分页存储系统,深入理解分页存储的原理和实现方式。
二、实验目标1. 设计并实现一个简单的分页存储系统;2. 理解分页存储的工作原理;3. 掌握分页存储的实现方法。
三、实验内容1. 设计页表结构页表是分页存储系统中的关键数据结构,用于记录页框与页面之间的映射关系。
在本实验中,我们可以使用一个简单的二维数组来表示页表。
其中,每一行表示一个页框,每一列表示一个页面,数组元素的值表示页面所在的页框号。
2. 实现地址转换地址转换是分页存储系统中的核心操作,它将逻辑地址转换为物理地址。
在本实验中,我们可以通过将逻辑地址的高位作为页号,低位作为页内偏移量,根据页表中的映射关系计算出物理地址。
3. 模拟页面置换算法页面置换算法是分页存储系统中解决内存不足问题的关键。
在本实验中,我们可以选择一种简单的页面置换算法,如FIFO(先进先出)算法或LRU(最近最少使用)算法,并在实验中模拟其运行过程。
四、实验步骤1. 设计页表结构根据实验要求,设计一个合适的页表结构,并初始化页表。
2. 实现地址转换根据页表的映射关系,实现逻辑地址到物理地址的转换函数。
3. 编写测试程序编写一个简单的测试程序,生成一系列逻辑地址,并通过地址转换函数将其转换为物理地址。
4. 模拟页面置换算法选择一种页面置换算法,并在测试程序中模拟其运行过程。
记录每次页面置换的情况,包括被置换出的页面和被置换入的页面。
五、实验结果与分析通过实验,我们可以得到一系列的物理地址,并根据页面置换算法的运行情况进行分析。
可以观察到不同页面置换算法对系统性能的影响,如命中率、缺页率等指标的变化。
六、实验总结通过本次实验,我们深入理解了分页存储的原理和实现方式。
通过设计和实现一个简单的分页存储系统,我们掌握了页表的结构和地址转换的方法,并熟悉了页面置换算法的运行过程。
基本分页存储管理
《操作系统》课程实验报告实验名称:基本分页存储管理姓名:学号:地点:指导老师:专业班级:软件外包11-01一、实验目的:1、熟悉并掌握基本分页存储管理的思想。
2、熟悉并掌握基本分页存储管理的分配和回收方式,并能够模拟实现。
二、实验内容:用高级语言模拟实现基本分页存储管理,要求:1、内存空间的初始化——可以由用户输入初始内存空间各个物理块情况。
(用二维矩阵的方式按物理块号,逐行给出每个物理块的状态,1——表示已分配,0——表示未分配,并能够将行标、列标转换为对应的物理块号,以查看或修改每一个块的状态,要求:初始时部分物理块已分配)2、基本分页的分配过程:由用户输入作业号和作业的大小(这里的大小是逻辑页面数),实现分配过程:空间充足,分配,修改状态矩阵的相应位置的值(值由0转变为1),并用专门的数据记录下该作业占用的物理块的块号,以备删除作业时回收空间。
3、作业空间的的回收:用户输入作业号,实现分区回收(通过相应的数据结构找到该作业占有的物理块号,将块号转变成对应的行标、列标,将对应位置的值由1转变成0就完成了回收)4、分区的显示:任何时刻,可以查看当前内存的情况(显示记录内存情况的矩阵的值)5、要求考虑:(1)内存空间不足的情况,要有相应的显示;(2)作业不能同名,但是删除后可以再用这个名字;(3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有相应的提示。
三、实验代码#include "stdio.h"#include "stdlib.h"int Block[10][10];int EachBlock[100][100];int AvailCount=0;typedef struct Page{int IDnum;int BlockSum;struct Page *next;}Page;Page *page=NULL;void init(){for(int i=0;i<10;i++)for(int j=0;j<10;j++){Block[i][j]=(int)rand()%2;if(Block[i][j]==0)AvailCount++;}for(int m=0;m<100;m++)for(int n=0;n<100;n++)EachBlock[m][n]=0;}void Create() //创建进程{int num,blockcount;Page *p,*q;p=page;printf("输入进程号:");scanf("%d",&num);while(p!=NULL){if(p->IDnum!=num)//判断是否已存在p=p->next;else{printf("该进程已存在并分配了物理块,重新输入:\n");scanf("%d",&num);p=page;}}printf("输入该进程所需要的物理块数目:");scanf("%d",&blockcount);if(blockcount>AvailCount)printf("内存物理块不足,不能完成分配!\n");else{q=new Page;q->IDnum=num;q->BlockSum=blockcount;q->next = NULL;int k=0;for(int i=0;i<10;i++)for(int j=0;j<10;j++)if(Block[i][j]==0&&q->BlockSum>k){Block[i][j]=1;k++;for(int m=0;m<100;m++)for(int n=0;n<100;n++)if(m==q->IDnum)EachBlock[m][i*10+j]=1;AvailCount--;}if(page==NULL){page=q;printf("分配成功!");}else{p=page;while(p->next != NULL)p = p->next;p->next=q;printf("分配成功!");}}}void Display() //输出物理块使用情况{Page *p;p=page;printf("内存物理块使用情况:\n");for(int i=0; i<10; i++){for(int j=0;j<10;j++)printf(" %d ",Block[i][j]);printf("\n");}printf("还有%d 个物理块未使用",AvailCount);printf("\n************各进程信息**************\n");printf("进程号\t 物理块数目\t物理块分布\n");while(p != NULL){printf("%4d\t%5d\t\t",p->IDnum,p->BlockSum);for(int i=0;i<100; i++)for(int j=0;j<100;j++)if(p->IDnum==i&&EachBlock[i][j]==1)printf("%d,",j+1);printf("\n");p = p->next;}}void Revoke() //回收进程{int num;Page *pre,*ptr;printf("输入要回收的进程号:");scanf("%d",&num);pre=page;ptr=pre;while(ptr!=NULL){if(ptr->IDnum==num)break;else{pre=ptr;ptr=ptr->next;}}if(ptr==NULL)printf("\n该进程不存在!\n");else{AvailCount+=ptr->BlockSum;for(int i=0;i<100;i++)for(int j=0;j<100;j++)if(ptr->IDnum==i&&EachBlock[i][j]==1)Block[j/10][j%10]=0;if(ptr==page){page=ptr->next;delete ptr;printf("该进程回收成功!");}else{pre->next=ptr->next;delete ptr;printf("该进程回收成功!");}}}void main() //主函数{int i;init();while(1){printf("\t ********************************************\n");printf("\t **************基本分页存储管理**************\n");printf("\n\t\t1>内存分配\t\t");printf("2>内存回收\n");printf("\t\t3>输出内存\t\t");printf("0>退出程序\n");printf("\t\t选择操作: \n");printf("\t ****************共一百个物理块**************\n");printf("\t ********************************************\n");scanf("%d",&i);switch(i){case 1:Create();break;case 2:Revoke();break;case 3:Display();break;case 0:exit(0);break;default:printf("\t\t输入有误,重新输入!");}}}四、实验结果五、实验总结这次试验的内容是模拟基本分页存储管理,本程序主要实现了对内存空间进行初始化,按照作业所需物理块数目对其进行空间分配,进程执行完毕后对其所占用的物理空间进行回收。
分页存储管理实验报告
一、实验目的1. 理解分页存储管理的基本原理和方法;2. 掌握分页存储管理中的页面置换算法;3. 熟悉分页存储管理的实现过程;4. 培养动手实践能力,提高对操作系统内存管理的认识。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发环境:Visual Studio 2019三、实验原理分页存储管理是一种将内存划分为固定大小的页面,并将进程的地址空间划分为同样大小的逻辑页的内存管理方式。
分页存储管理的主要优点是消除了外部碎片,提高了内存的利用率。
以下是分页存储管理的关键概念:1. 页面:内存划分为固定大小的块,称为页面。
页面大小通常为4KB或8KB。
2. 逻辑页:进程的地址空间划分为同样大小的块,称为逻辑页。
3. 页表:用于记录逻辑页与物理页的映射关系。
四、实验内容1. 初始化内存:创建一个模拟的内存空间,用数组表示。
初始化时,内存中的一部分页面被占用,其他页面为空闲状态。
2. 进程调度:模拟进程的调度过程,包括进程的创建、销毁和页面请求。
3. 页面置换算法:实现不同的页面置换算法,如先进先出(FIFO)、最近最少使用(LRU)等。
4. 页面映射:根据进程的页面请求,查找页表,将逻辑页映射到物理页。
5. 页面回收:当进程销毁或页面不再需要时,回收对应的物理页。
五、实验步骤1. 初始化内存:创建一个大小为1024的数组,模拟内存空间。
其中,前256个元素表示被占用的页面,其余元素表示空闲页面。
2. 创建进程:模拟进程的创建过程,包括进程的编号、所需页面数和页面请求序列。
3. 页面置换算法:实现FIFO和LRU两种页面置换算法。
FIFO算法按照进程创建的顺序进行页面置换;LRU算法根据页面在内存中驻留时间的长短进行页面置换。
4. 页面映射:根据进程的页面请求,查找页表,将逻辑页映射到物理页。
如果请求的页面已在内存中,则直接返回物理页号;如果请求的页面不在内存中,则根据页面置换算法替换一个页面,并将请求的页面加载到内存中。
请求分页存储管理模拟实验
操作系统模拟实验实验名称:请求分页存储管理模拟实验实验目的:通过实验了解windows系统中的线程同步如何使用,进一步了解操作系统的同步机制。
实验内容:调用Windows API,模拟解决生产者-消费者问题;思考在两个线程函数中哪些是临界资源?哪些代码是临界区?哪些代码是进入临界区?哪些代码是退出临界区?进入临界区和退出临界区的代码是否成对出现?学习Windows API中的如何创建线程,互斥,临界区等。
程序运行结果:源程序:#include "stdAfx.h"//包含头文件以支持多线程#include "windows.h"#include "stdio.h"//用于标志所有的子线程是否结束//每次子线程结束后,此值便加1。
static long ThreadCompleted = 0;//互斥量HANDLE mutex;//信号量,用于生产者通知消费者HANDLE full;//信号量,用于消费者通知生产者HANDLE empty;//信号量,当所有的子线程结束后,通知主线程,可以结束。
HANDLE evtTerminate;//生产标志#define p_item 1//消费标志#define c_item 0//哨兵#define END 10//缓冲区最大长度const int max_buf_size=11;const int cur_size=10;//缓冲区定义int BUFFER[max_buf_size];//放消息指针int in=0;//取消息指针int out=0;int front=0;int tail=0;int sleep_time=1000;bool flag=true;//线程函数的标准格式unsigned long __stdcall p_Thread(void *theBuf);unsigned long __stdcall c_Thread(void *theBuf);//打印缓冲区内容void PrintBuf(int buf[],int buf_size);int main(int argc, char* argv[]){//初始化缓冲区unsigned long TID1, TID2;for(int i=0;i<cur_size;i++)BUFFER[i]=0;//互斥量和信号量的创建,函数用法可查看MSDNmutex=CreateMutex(NULL,false,"mutex");full=CreateSemaphore(NULL,0,1,"full");empty=CreateSemaphore(NULL,max_buf_size,max_buf_size,"empty");evtTerminate = CreateEvent(NULL, FALSE, FALSE, "Terminate");//创建一个生产者线程和消费者线程。
分页存储管理实验报告
分页存储管理实验报告篇一:分页存储管理的模拟实验上机报告分页存储管理的模拟实验上机报告页面管理的基本原理及方法:各进程的虚拟空间被划分成若干个长度相等的页(page)。
页长的划分和内存外存之间的数据传输速度以及内存大小等有关。
页式管理还把内存空间也按也的大小划分为页面(page frame)。
然后把页式虚拟地址与内存页面物理地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。
在作业或进程开始执行之前,把该作业或进程的程序段和数据全部装入内存的各个页面中,并通过页表(page mapping table)和硬件地址变换机构实现虚拟地址到内存物理地址的地址映射。
1. 内存页面分配静态页面管理的第一步是为要求内存的作业或进程分配足够的页面。
系统依靠存储页面表,请求表及页表来完成内存的分配工作。
a. 页表页表由页号与页面号组成。
如右图所示页表的大小由进程或作业的长度决定。
例如,对于一个每页长1k,大小为20k的进程来说,如果一个内存单元存放一个页表项,则只要分配给该页表20个存储单元即可。
页式管理是每个进程至少拥有一个页表。
实验中对页表的定义如下(采用数组形式,数组下标表示页号,数组单元存放与数组下标(页号)相应的页面号):int pagetable[100] b.请求表(作业申请表)请求表用来确定作业或进程的虚拟空间的各页在内存中的对应位置。
为了完成这个认为,系统必须知道每个作业或进程的页表起始地址(本实验中假定为0)和长度,以进行内存分配和地址变换。
另外请求表中还包括每个作业或进程所要求的页面数。
请求表整个系统一张,实验中对请求表的定义如下(采用结构体数组形式,并将页表也作为其中一个成员(即域)):# define u 5 struct application_table{char name[8];/*作业名*/int size; /*作业大小――即将上表中的请求页面数改用字节表示*/int paddress; /*页表起始地址*/ int length;/*页表长度――以页面数表示*/int state; /*内存的分配状态,以分配的用1表示,未分配的用0表示*/int pagetable[100];/*页表,放在这里是为了方便虚地址转换及作业撤销的操作*/ }application[u];c.存储页面表(本实验中采用位示图法)位示图也是整个系统一张,它指出内存各页面是否已被分配出去,以及未分配页面的总数。
分页存储实验报告
一、实验目的1. 理解分页存储的基本原理和作用。
2. 掌握分页存储的实现方法。
3. 分析分页存储对系统性能的影响。
4. 提高对虚拟内存管理的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3. 实验工具:IDLE三、实验内容1. 分页存储的基本原理分页存储是将程序的逻辑地址空间划分为若干个大小相等的页,并将这些页存储在物理内存中。
在分页存储中,页表用于记录每个页在物理内存中的位置。
2. 分页存储的实现方法(1)定义数据结构首先,定义一个类来表示页表,该类包含以下属性:- 页号:表示页在逻辑地址空间中的编号。
- 物理页号:表示页在物理内存中的编号。
- 是否在内存:表示页是否在物理内存中。
(2)初始化页表在程序开始时,初始化页表,将所有页都标记为不在内存。
(3)处理页表请求当程序访问一个逻辑地址时,首先检查页表,如果该页在内存中,则直接访问;如果不在内存,则需要执行页面置换算法,将一个页替换出内存,并将需要访问的页加载到内存中。
(4)页面置换算法本实验采用LRU(最近最少使用)算法作为页面置换算法。
LRU算法的基本思想是:当一个页需要被替换出内存时,选择最近最少被访问的页进行替换。
3. 分析分页存储对系统性能的影响(1)提高内存利用率分页存储可以将程序中不常用的页存储在磁盘上,从而提高内存利用率。
(2)减少内存碎片分页存储可以减少内存碎片,因为每个页的大小是固定的,不会出现大小不一的内存碎片。
(3)降低系统性能分页存储会降低系统性能,因为每次访问一个页时,都需要查询页表,如果页不在内存中,还需要执行页面置换操作,这将增加系统的开销。
四、实验步骤1. 编写程序实现分页存储的基本功能。
2. 设置不同大小的页,观察对内存利用率的影响。
3. 设置不同的页面置换算法,比较其对系统性能的影响。
4. 分析实验结果,得出结论。
五、实验结果与分析1. 设置不同大小的页当页的大小较小时,内存利用率较低,因为每个页只包含少量数据。
分页存储管理实验报告
分页存储管理实验报告分页存储管理实验报告篇一:分页存储管理的模拟实验上机报告分页存储管理的模拟实验上机报告页面管理的基本原理及方法:各进程的虚拟空间被划分成若干个长度相等的页(page)。
页长的划分和内存外存之间的数据传输速度以及内存大小等有关。
页式管理还把内存空间也按也的大小划分为页面(page frame)。
然后把页式虚拟地址与内存页面物理地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。
在作业或进程开始执行之前,把该作业或进程的程序段和数据全部装入内存的各个页面中,并通过页表(page mapping table)和硬件地址变换机构实现虚拟地址到内存物理地址的地址映射。
1. 内存页面分配静态页面管理的第一步是为要求内存的作业或进程分配足够的页面。
系统依靠存储页面表,请求表及页表来完成内存的分配工作。
a. 页表页表由页号与页面号组成。
如右图所示页表的大小由进程或作业的长度决定。
例如,对于一个每页长1k,大小为20k的进程来说,如果一个内存单元存放一个页表项,则只要分配给该页表20个存储单元即可。
页式管理是每个进程至少拥有一个页表。
实验中对页表的定义如下(采用数组形式,数组下标表示页号,数组单元存放与数组下标(页号)相应的页面号):int pagetable[100] b.请求表(作业申请表)请求表用来确定作业或进程的虚拟空间的各页在内存中的对应位置。
为了完成这个认为,系统必须知道每个作业或进程的页表起始地址(本实验中假定为0)和长度,以进行内存分配和地址变换。
另外请求表中还包括每个作业或进程所要求的页面数。
请求表整个系统一张,实验中对请求表的定义如下(采用结构体数组形式,并将页表也作为其中一个成员(即域)):#define u 5 struct application_table{char name[8];/*作业名*/int size;/*作业大小――即将上表中的请求页面数改用字节表示*/int paddress; /*页表起始地址*/ int length;/*页表长度――以页面数表示*/int state; /*内存的分配状态,以分配的用1表示,未分配的用0表示*/int pagetable[100];/*页表,放在这里是为了方便虚地址转换及作业撤销的操作*/ }application[u];c.存储页面表(本实验中采用位示图法)位示图也是整个系统一张,它指出内存各页面是否已被分配出去,以及未分配页面的总数。
分区存储管理模拟实验报告
分区存储管理模拟实验报告分区存储管理模拟实验报告1.实验目的了解动态分区存储管理方式中的数据结构和分配算法,加深对动态分区存储管理方式及其实现技术的理解。
2. 实验内容▪用C语言或Pascal语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程Allocate()和回收过程Free()。
其中,空闲分区采用空闲分区链来组织,内存分配时,优先使用空闲区低地址部分的空间。
▪假设初始状态,可用内存空间为640KB,作业请求序列如下(也可以编程从键盘输入,R 表示请求,F表示释放):✧作业1请求130 KB。
✧作业2请求60 KB。
✧作业3请求100 KB。
到第一个足以满足要球的空闲块就停止查找,并把它分配出去;如果该空闲空间与所需空间大小一样,则从空闲表中取消该项;如果还有剩余,则余下的部分仍留在空闲表中,但应修改分区大小和分区始址。
最佳适应算法:当要分配内存空间时,就查找空闲表中满足要求的空闲块,并使得剩余块是最小的。
然后把它分配出去,若大小恰好合适,则直按分配;若有剩余块,则仍保留该余下的空闲分区,并修改分区大小的起始地址。
内存回收:将释放作业所在内存块的状态改为空闲状态,删除其作业名,设置为空。
并判断该空闲块是否与其他空闲块相连,若释放的内存空间与空闲块相连时,则合并为同一个空闲块,同时修改分区大小及起始地址。
typedef struct freearea{}ElemType;定义一个空闲区说明表结构,每申请一个作业,改作业便具有此结构体typedef struct DuLNode{}DuLNode,*DuLinkList;定义一个双向链表Status Initblock(){}开创带头结点的内存空间链表,通过双向链表把申请的作业链接起来,作业的插入和删除,和链表中节点的插入和删除类似。
双向链表如图1所示Status First_fit(int ID,int request){}传入作业名及申请量采用首次适应算法实现动态内存分区分配的模拟,初始态640KB,只是一个虚态,每申请成功一个作业,便相应的640KB做相应的减少,同过双向链表模拟主存的分配情况。
分页存储管理实验报告(word文档良心出品)
操作系统实验三报告一.实验名称:分页存储管理二.实验目的:了解分页存储管理在内存空间分配的作用三.实验内容:分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,相应的,也把内存空间分成与页面相同大小的若干个存储块,称为物理块或页框,同样加以编号,在为进程分配内存时,以块为单位将进程的若干个也分别装入到多个可以不相邻的物理块中。
系统为每个进程建立了一张页面映像表,简称页表。
位示图是利用二进制的一位来表示磁盘中的一个盘块的使用情况,这里用位示图来表示内存分配情况。
四.实验代码#include <stdafx.h>#include <stdlib.h>#include <stdio.h>typedef int datatype;typedef struct node{datatype pageNum,blockNum;struct node *next;}linknode;typedef linknode *linklist;linklist creatlinklist(int n){linklist head,r,s;int x,y,i=0;head=r=(linklist)malloc(sizeof(linknode));printf("开始创建页表\n");printf("请分别输入页表的页号及块号(-1表示空):\n");printf("\n页号块号\n");while (i<n){scanf("%d %d",&x,&y);s=(linklist)malloc(sizeof(linknode));s->pageNum=x;s->blockNum=y;r->next=s;r=s;i++;}r->next=NULL;return head;}void print(linklist head){linklist p;p=head->next;printf("\n该页表为:");printf("\n页号块号\n");while(p){printf("%d%7d\n",p->pageNum,p->blockNum );p=p->next;}printf("\n");}/*初始化位示图,将值全置为零,0表示空闲状态*/void init(int g[100][100],int N){int i,j;for(i=0;i<100;i++){for(j=0;j<100;j++){g[i][j]=0;}}g[N+1][0]=N*N;}/*对作业的每一个页进行分配对应位示图里的块*/linklist Dis(linklist head,int g[100][100],int n,int N){linklist p;int i,j;p=head->next;if(n<=g[N+1][0]){while(p){for(i=0;i<N;i++){for(j=0;j<N;j++){if(g[i][j]==0){p->blockNum=N*i+j;g[i][j]=1;g[N+1][0]--;break;}}break;}p=p->next;}return head;}}/*回收已经完成的页*/linklist Recy(linklist head,int g[100][100],int n,int N){int i,j;linklist p;p=head->next;while(p&&p->pageNum!=n){p=p->next;}if(p){i=p->blockNum/N;j=p->blockNum%N;g[i][j]=0;g[N+1][0]++;p->blockNum=-1;}return head;}/*打印位示图*/void printStr(int g[100][100],int N) {int i,j;printf("此时位示图为:\n ");for(i=0;i<N;i++){printf(" ");printf("%d",i);}printf("\n");for(i=0;i<N;i++){printf("%d",i);for(j=0;j<N;j++){printf(" ");printf("%d",g[i][j]);}printf("\n");}}void main(){int n,N,x,y;int graph[100][100];linklist head;printf("输入位示图的字长:");scanf("%d",&N);printf("输入作业的页数:");scanf("%d",&n);head=creatlinklist(n);print(head);init(graph,N);printStr(graph,N);printf("\n现在进行作业分配:");head=Dis(head,graph,n,N);print(head);printStr(graph,N);printf("是否回收已完成的页,“是”1,“否”0:");scanf("%d",&x);if(x) //判断是否要回收{printf("\n请输入您要回收的页号:");scanf("%d",&y);head=Recy(head,graph,y,N);print(head);printStr(graph,N);}}五.实验截图:六.实验心得:通过这次实验,了解到分页存储管理是将一个进程的逻辑地址空间分成若干个大小相等的片,称为页面或页,并为各页加以编号,相应的,也把内存空间分成与页面相同大小的若干个存储块,称为物理块或页框,同样加以编号,在为进程分配内存时,以块为单位将进程的若干个也分别装入到多个可以不相邻的物理块中。
分页式管理实验报告参考模板
题目连续式与分页式主存管理模式的模拟实现学生姓名学号学院专业计算机科学与技术专业指导教师赵晓平二O一二年六月十一日一、实验目的模拟在连续分配与分页管理两种方式下,主存空间的分配与回收,帮助学生加深了解存储器管理的工作过程。
注意,该实验为模拟实验,并不要求进行真正的内存分配与回收,主要是编写程序模拟其中过程即可。
二、实验内容1 连续式分配1、 在连续分配方式下,设计一个动态分区分配与回收的内存管理程序。
2、 动态分区分配按作业需要的主存大小来分割分区。
当要装入一个作业时,根据作业需要、、的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。
3、 设置一张全局分区状态表说明当前内存分配状态,例如下所示:4、 设置一张空闲分区表描述当前空闲分区分布状况,可采用数组或链表来实现,数组可参考以下格式:第一栏 第二栏说明:起址——指出一个空闲区的主存起始地址。
长度——指出从起始地址开始的一个连续空闲的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白(无效),可用来登记新的空闲区。
5、 在作业撤销后,系统需要回收分区。
在空闲分区表中找到一个空表目登记回收分区的起址和长度,并且修改表目状态为未分配。
注意:由于分区的个数不定,所以空闲分区表中应有适量的状态为“空表目”的登记栏目,否则造成表格“溢出”无法登记。
6、 在回收分区时,应考虑相邻空闲分区合并。
7、 在完成一次作业装入后,都需要输出:本次分配的分区起址与长度,全局分区状态表,空闲分区表的内容。
若在分配中发生分割,需要说明分割后新空白分区的起址与长度。
8、 在完成一次作业撤销后,都需要输出:本次回收的分区起址与长度,全局分区状态表,空闲分区表的内容。
若发生相邻空闲分区合并,需要说明哪几个分区合并在一起,合并后的起址与长度 2、分页式管理1、 设计一个基本分页存储管理程序2、 分页式存储器把主存分成大小相等的若干块,作业的信息也按块的大小分页,作业装入主存时按页分散存放在主存的空闲块中。
分页存储管理实验报告
分页存储管理实验报告分页存储管理实验报告引言在计算机科学领域,存储管理是一个重要的课题。
随着计算机应用的不断发展,对存储管理的要求也越来越高。
本实验旨在通过实践,深入了解分页存储管理的原理和实现方式,以及其在计算机系统中的应用。
一、实验目的本实验的主要目的是通过实践,加深对分页存储管理的理解。
具体目标如下:1. 理解分页存储管理的原理和概念;2. 掌握分页存储管理的实现方式;3. 熟悉分页存储管理在计算机系统中的应用。
二、实验原理分页存储管理是一种将物理内存划分为固定大小的页框,并将逻辑地址空间划分为相同大小的页的存储管理方式。
其主要原理如下:1. 将逻辑地址划分为页号和页内偏移两部分;2. 通过页表将逻辑地址映射到物理地址;3. 利用页表中的页表项实现地址映射。
三、实验过程1. 初始化页表:根据系统的物理内存大小和页框大小,计算出页表的大小,并进行初始化。
2. 地址映射:根据逻辑地址的页号,查找页表中对应的页表项,获取物理页框号,并将页内偏移与物理页框号组合得到物理地址。
3. 存储管理:根据物理地址,将数据存储到物理内存中的相应位置,或从物理内存中读取数据。
4. 内存分配:根据应用程序的需要,分配合适大小的物理内存页框,并更新页表。
四、实验结果通过实验,我们成功实现了分页存储管理,并进行了一系列测试。
实验结果表明,分页存储管理具有以下优点:1. 提高了内存利用率:通过将逻辑地址划分为固定大小的页,可以更好地利用物理内存空间。
2. 简化了内存管理:通过页表的使用,可以方便地进行地址映射和内存分配。
3. 提高了系统的稳定性:分页存储管理可以有效隔离不同进程之间的内存空间,提高了系统的稳定性和安全性。
五、实验总结本实验通过实践,深入了解了分页存储管理的原理和实现方式,并通过一系列测试验证了其在计算机系统中的应用效果。
实验结果表明,分页存储管理是一种高效、稳定的内存管理方式,可以提高系统的性能和稳定性。
分页管理实验报告
一、实验目的1. 理解分页存储管理的基本原理和实现方法。
2. 掌握分页存储管理的优缺点。
3. 分析分页存储管理在实际应用中的效果。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3. 开发工具:PyCharm三、实验内容1. 分页存储管理的基本原理分页存储管理是一种虚拟存储管理技术,将程序的逻辑地址空间划分为若干个固定大小的页,并将物理内存也划分为同样大小的页帧。
程序在执行时,只将当前需要的页加载到内存中,其余页面则在需要时再进行加载,从而实现程序的虚拟存储。
2. 分页存储管理实现方法(1)分页地址转换分页地址转换通过页表实现。
页表记录了逻辑地址与物理地址的对应关系。
当程序访问内存时,需要根据页表将逻辑地址转换为物理地址。
(2)页面置换算法页面置换算法用于解决内存中已满,而新页面需要加载时如何选择页面替换的问题。
常见的页面置换算法有:FIFO(先进先出)、LRU(最近最少使用)、OPT(最优页面置换)等。
(3)缺页中断当程序访问的页面不在内存中时,会发生缺页中断。
操作系统会根据页面置换算法选择一个页面进行替换,并将所需的页面加载到内存中。
3. 实验步骤使用Python编写分页存储管理程序,实现分页地址转换、页面置换算法和缺页中断等功能。
(2)测试程序编写测试用例,模拟程序运行过程中的分页操作,观察分页存储管理的效果。
(3)分析实验结果根据实验结果,分析分页存储管理的优缺点,以及在实际应用中的效果。
四、实验结果与分析1. 分页存储管理程序实现通过Python编写分页存储管理程序,实现分页地址转换、页面置换算法和缺页中断等功能。
2. 实验结果(1)分页地址转换当程序访问内存时,分页存储管理程序能够正确地将逻辑地址转换为物理地址。
(2)页面置换算法通过FIFO、LRU和OPT等页面置换算法,程序能够有效地处理内存中的页面替换问题。
(3)缺页中断程序在访问未在内存中的页面时,能够正确地发生缺页中断,并将所需的页面加载到内存中。
存储管理实验报告
存储管理实验报告题目:1。
存储管理描述请求分页存储管理。
一.产生一个作业及作业页面序列P(pi),例如:P(0,2,3,4,1,5,2,3,0,4,1,5)。
二.分配物理内存块数M。
三.采用FIFO,LRU置换算法。
四.设计原理:本程序提供两种分区管理法供用户使用,这两种算法是最佳适应算法和首次适应算法。
最佳适应算法要求将所有的空闲区,按其大小以递增的顺序形成一空闲区链。
这样,第一次找到的满足要求的空闲区,必然是最优的。
但该算法会留下许多这样难以利用的小空闲区。
首次适应算法要求空闲分区链以地址递增的次序链接。
在进行内存分配时,从链首开始顺序查找,直至找到一个能满足其大小要求的空闲分区为止。
然后,再按照作业的大小,从该分区中划出一快内存空间分配该请求者,余下的空闲分区仍留在空闲链中。
三.不足之处:该程序可以用文件形式输入作业的信息,但是该文件没有绑定在程序中。
不过,用户用键盘输入的作业的信息会自动保存到该文件中,下次当以文件形式输入作业信息时,文件中的内容是上一次用户用键盘输入的内容。
四.源程序以及解释:#include<stdio.h>#include<time.h>#include<stdlib.h>int memoryStartAddress = -1;int memorySize = -1;struct jobList//作业后备队列的链结点{int id; //作业的ID号int size; //作业的大小int status; //作业状态struct jobList *next;};struct freeList //空闲链的链结点{int startAddress; //空闲分区的首地址int size; //空闲分区的大小struct freeList *next;};struct usedList //已分配内存的作业链{int startAddress; //以分配内存的首地址int jobID;struct usedList *next;};void errorMessage(void) //出错信息{printf("\n\t错误!\a");printf("\n按任意键继续!");getch();exit(1);}void openFile(FILE **fp,char *filename,char *mode) //打开文件函数{if((*fp = fopen(filename,mode)) == NULL){printf("\n不能打开%s.",filename);errorMessage();}}void makeFreeNode(struct freeList **empty,int startAddress,int size)//申请内存空间{if((*empty = malloc(sizeof(struct freeList))) == NULL){printf("\n没有足够空间.");errorMessage();}(*empty)->startAddress = startAddress; //当有足够空间时,则分配(*empty)->size = size;(*empty)->next = NULL;}void iniMemory(void) //输入要求分配内存的首地址,大小{char MSA[10],MS[10];printf("\n请输入要分配内存的首地址!");scanf("%s",MSA);memoryStartAddress = atoi(MSA);printf("\n请输入要分配内存的大小!");scanf("%s",MS);memorySize = atoi(MS);}char selectFitMethod(void) //选择分区管理算法{FILE *fp;char fitMethod;do{printf("\n\n请选择分区管理的算法!\\n 1 最佳适应算法\\n 2 首次适应算法\n");fitMethod = getche();}while(fitMethod < '1' || fitMethod > '3'); //选择出错时openFile(&fp,"d:\\result.cl","a");switch(fitMethod){case '1':fprintf(fp,"\n\n\n\n\t 最佳适应算法");fprintf(fp,"\n**********************************************");break;case '2':fprintf(fp,"\n\n\n\n\t首次适应算法");fprintf(fp,"\n**********************************************");break;}fclose(fp);return fitMethod;}void inputJob(void) //输入作业的信息{int /*id,size, */status = 0,jobnum = 0;FILE *fp;char id[10],size[10];openFile(&fp,"d:\\job.cl","w");fprintf(fp,"作业名\t大小\t状态");printf("\n\n\n\n请输入作业名和大小!\n输入0 0退出,job_ID由数字组成\n\n\njob_ID\tsize\n");do{/* scanf("%d%d",&id,&size); */scanf("%s\t%s",id,size); //保存作业ID,大小if(atoi(id) > 0 && atoi(size) > 0){fprintf(fp,"\n%s\t%s\t%d",id,size,status);/* fprintf(fp,"\n%d\t%d\t%d",id,size,status); */jobnum++;}else break;}while(1);if(jobnum)printf("\n完成输入!");else{printf("\n没有请求分配内存.");errorMessage();}fclose(fp);}int makeJobList(struct jobList **jobs) //把作业插入分区{char jobID[10],size[10],status[10];struct jobList *rear;FILE *fp;openFile(&fp,"d:\\job.cl","r");fscanf(fp,"%s%s%s",jobID,size,status);if((*jobs = malloc(sizeof(struct jobList))) == NULL) //当没有空闲分区时{printf("\n没有足够空间.");fclose(fp);errorMessage();}rear = *jobs;(*jobs) -> next = NULL;while(!feof(fp)){struct jobList *p;fscanf(fp,"%s%s%s",jobID,size,status);if((p = malloc(sizeof(struct jobList))) == NULL){printf("\n没有足够空间.");fclose(fp);errorMessage();}p -> next = rear -> next; //插入已在分区的作业队列中rear -> next = p;rear = rear -> next;rear -> id = atoi(jobID);rear -> size = atoi(size);rear -> status = atoi(status);}fclose(fp);return 0;}int updateJobFile(struct jobList *jobs){FILE *fp;struct jobList *p;openFile(&fp,"d:\\job.cl","w");fprintf(fp,"job_ID\tsize\tstatus");for(p = jobs -> next;p;p = p -> next)fprintf(fp,"\n%d\t%d\t%d",p -> id,p -> size,p -> status);fclose(fp);return 0;}int showFreeList(struct freeList *empty) //在屏幕上显示空闲分区{FILE *fp;struct freeList *p = empty -> next;int count = 0;openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n显示空闲内存");printf("\n\n显示空闲内存");if(p){fprintf(fp,"\nnumber\tsize\tstartAddress");printf("\n序号\t大小\t开始地址"); //显示空闲分区的大小和首地址for(;p;p = p -> next){fprintf(fp,"\n%d\t%d\t%d",++count,p -> size,p -> startAddress);printf("\n%d\t%d\t%d",count,p -> size,p -> startAddress);}fclose(fp);return 1;}Else //没有空闲分区{fprintf(fp,"\n内存已分配完!");printf("\n内存已分配完!");fclose(fp);return 0;}}void getJobInfo(struct jobList *jobs,int id,int *size,int *status) //查找作业是否在分区中{struct jobList *p = jobs->next;while(p && p->id != id) //删除作业p = p->next;if(p == NULL){printf("\n不能找到作业: %d .",id);errorMessage();}else{*size = p -> size;*status = p -> status;}}void updateJobStatus(struct jobList **jobs,int id,int status) //改变作业的状态{struct jobList *p = (*jobs)->next;while(p && p->id != id)p = p->next;if(p == NULL){printf("\n不能找到作业: %d .",id);errorMessage();}p -> status = status; //作业状态}int showUsedList(struct jobList *jobs,struct usedList *used) //显示以分配的分区{FILE *fp;struct usedList *p = used -> next;int count = 0,size,status;openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n显示已分配的内存");printf("\n\n显示已分配的内存");if(p){fprintf(fp,"\nnumber\t作业名\t大小\t开始地址");printf("\nnumber\t作业名\t大小\t开始地址"); //显示分区中的作业信息for(;p;p = p -> next){getJobInfo(jobs,p -> jobID,&size,&status);fprintf(fp,"\n%d\t%d\t%d\t%d",++count,p -> jobID,size,p -> startAddress);printf("\n%d\t%d\t%d\t%d",count,p -> jobID,size,p -> startAddress);}fclose(fp);return 1;}Else //分区中没有作业{fprintf(fp,"\n内存中没有作业.");printf("\n内存中没有作业.");fclose(fp);return 0;}}int showJobList(struct jobList *jobs) //分区上的作业{struct jobList *p;p = jobs->next;if(p == NULL){printf("\n列表上没有作业.");return 0;}printf("\n\nT列表上的作业如下:\n作业名\t大小\t状态"); //显示作业信息while(p)printf("\n%d\t%d\t%d",p->id,p->size,p->status);p = p->next;}return 1;}void moveFragment(struct jobList *jobs,struct freeList **empty,struct usedList **used) //当回收一部分分区后,进行碎片紧凑{int size,status;struct usedList *p;int address = memoryStartAddress;if((*empty)->next == NULL) //当没有空闲分区分配时,可以回收已分配内存{printf("\n内存已用完.\\n你可以先回收一些内存或者\\n按任意键再试一次!");getch();return;}for(p = (*used) -> next;p;p = p-> next) //插入作业{p -> startAddress = address;getJobInfo(jobs,p -> jobID,&size,&status);address += size;}(*empty) -> next -> startAddress = address; //删除作业,回收内存(*empty) -> next -> size = memorySize - (address - memoryStartAddress);(*empty) -> next -> next = NULL;}void order(struct freeList **empty,int bySize,int inc) //按顺序排列分区的作业{struct freeList *p,*q,*temp;int startAddress,size;for(p = (*empty) -> next;p;p = p -> next){for(temp = q = p;q;q = q -> next){switch(bySize){case 0 : switch(inc){case 0:if(q->size < temp->size) //交换作业位置temp = q;break;default:if(q->size > temp->size)//交换作业位置temp = q;break;} break;default: switch(inc){case 0:if(q->startAddress < temp->startAddress)temp = q;break; //交换作业位置default:if(q->startAddress > temp->startAddress)temp = q;break; //交换作业位置} break;}}if(temp != p){startAddress = p->startAddress;size = p->size;p->startAddress = temp->startAddress;p->size = temp->size;temp->startAddress = startAddress;temp->size = size;}}}int allocate(struct freeList **empty,int size) //按要求把分区分该作业{struct freeList *p,*prep;int startAddress = -1;p = (*empty) -> next;while(p && p->size < size)//没有足够分区,删除作业p = p -> next;if(p != NULL){if(p -> size > size) //当有足够分区,直接分配{startAddress = p -> startAddress;p -> startAddress += size;p -> size -= size;}else //将整个分区分给一个作业{startAddress = p -> startAddress;prep = *empty;while(prep -> next != p)prep = prep -> next;prep -> next = p -> next;free(p);}}else printf("\n你可以拼接碎片."); /* Unsuccessful ! */return startAddress;}void insertUsedNode(struct usedList **used,int id,int startAddress)//在分区中插入作业{struct usedList *q,*r,*prer;if((q = malloc(sizeof(struct usedList))) == NULL) //没有足够空间时{printf("\nNot enough to allocate for the used node .");errorMessage();}q -> startAddress = startAddress; //插入作业q -> jobID = id;prer = *used;r = (*used) -> next;while(r && r->startAddress < startAddress){prer = r;r = r -> next;}q -> next = prer -> next;prer -> next = q;}int finishJob(struct usedList **used,int id,int *startAddress) //删除作业,回收分区{struct usedList *p,*prep;prep = *used;p = prep -> next;while(p && p -> jobID != id) //删除作业{prep = p;p = p -> next;}if(p == NULL){printf("\n作业: %d 不在内存!",id); //找不到要删除的作业return 0;}else{*startAddress = p->startAddress;prep -> next = p -> next;free(p);return 1;}}void insertFreeNode(struct freeList **empty,int startAddress,int size)//插入空闲分区{struct freeList *p,*q,*r;for(p = *empty;p -> next;p = p -> next) ;if(p == *empty || p -> startAddress + p -> size < startAddress)//对空闲分区进行排列{makeFreeNode(&r,startAddress,size);r -> next = p -> next;p -> next = r;return ;}if(p -> startAddress + p -> size == startAddress) //插入空闲分区{p -> size += size;return ;}q = (*empty) -> next;if(startAddress + size == q -> startAddress) //插入空闲分区{q -> startAddress = startAddress;q -> size += size;}else if(startAddress + size < q -> startAddress) //插入空闲分区{makeFreeNode(&r,startAddress,size);r -> next = (*empty) -> next;(*empty) -> next = r;}else{while(q -> next && q -> startAddress < startAddress) //插入空闲分区{p = q;q = q -> next;}if(p -> startAddress + p -> size == startAddress &&\q -> startAddress == startAddress + size) //插入空闲分区{p -> size += size + q -> size;p -> next = q -> next;free(q);}else if(p -> startAddress + p -> size == startAddress &&\q -> startAddress != startAddress + size) //插入空闲分区{p -> size += size;}else if(p -> startAddress + p -> size != startAddress &&\q -> startAddress == startAddress + size) //插入空闲分区{q -> startAddress = startAddress;q -> size += size;}else{makeFreeNode(&r,startAddress,size); //申请作业空间r -> next = p -> next;p -> next = r;}}}void main(void){char fitMethod; //定义变量FILE *fp; //定义变量struct jobList *jobs; //定义一个队列struct freeList *empty;//定义一个队列struct usedList *used;//定义一个队列if((used = malloc(sizeof(struct usedList))) == NULL){printf("\n没有足够空间.");errorMessage();}used -> next = NULL;remove("d:\\result.cl");makeFreeNode(&empty,0,0);while(1) //界面设计{char ch,step; //定义变量int id,size,startAddress,status; //定义变量struct jobList *q;printf("\n 1 输入作业的信息.\\n 2 作业放到内存.\\n 3 完成作业,并回收内存.\\n 4 当前空闲的内存.\\n 5 当前已分配的内存.\\n 6 拼接碎片.\\n 7 退出.");printf("\n请选择.\n");step = getche();printf("\n");switch(step){case '1': //当选择1时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t输入作业的信息:)");used -> next = NULL; //初始化队列empty->next = NULL; //初始化队列iniMemory();makeFreeNode(&(empty->next),memoryStartAddress,memorySize);fprintf(fp,"\n\n\n你用文件形式输入吗?(Y/N) : ");//是否用文件形式输出printf("\n\n\n你用文件形式输入吗?(Y/N ): \n");ch = getche();fprintf(fp,"\n%c",ch);fclose(fp);if(ch != 'Y'&& ch != 'y') //当选择用文件形式输出时{inputJob();}makeJobList(&jobs);if(ch == 'Y'|| ch == 'y') //读入文件的作业信息{for(q = jobs->next;q;q = q->next){if(q->status == 1){startAddress = allocate(&empty,q->size);if(startAddress != -1){insertUsedNode(&used,q->id,startAddress);}}}}fitMethod = selectFitMethod();break;case '2': //当选择2时if(memoryStartAddress < 0 || memorySize < 1){printf("\n\nBad memory allocated !\a");break;}openFile(&fp,"d:\\result.cl","a"); //打开文件fprintf(fp,"\n\n\t把作业放到内存");fprintf(fp,"\n\n\n你用键盘输入作业信息吗?(Y/N): ");printf("\n\n\n你用键盘输入作业信息吗?(Y/N): \n");ch = getche();fprintf(fp,"\n%c",ch);fclose(fp);if(ch != 'Y' && ch != 'y') //把作业放到分区中{for(q = jobs->next;q;q = q->next){if(q->status == 0){switch(fitMethod) //用不同分区管理算法{case '1': order(&empty,0,0);break;case '2': order(&empty,0,1);break;case '3': order(&empty,1,0);break;case '4': order(&empty,1,1);break;}startAddress = allocate(&empty,q->size);if(startAddress != -1){insertUsedNode(&used,q->id,startAddress);//把作业插入到以分配内存中updateJobStatus(&jobs,q->id,1);}}}updateJobFile(jobs);}else{showJobList(jobs); //显示可操作的作业openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n请从上面的作业中选择一个作业,输入作业名.");printf("\n请从上面的作业中选择一个作业,输入作业名.");scanf("%d",&id);fprintf(fp,"%d\n",id);getJobInfo(jobs,id,&size,&status); //把作业放入内存switch(status) //作业的不同状态{case 0: printf("\nOk !作业的状态是运行状态!");fprintf(fp,"\nOk!作业的状态是运行状态!");fclose(fp);break;case 1: printf("\n作业在内存中!");fprintf(fp,"\n作业在内存中!");fclose(fp);goto label;case 2: printf("\n作业已完成!");fprintf(fp,"\n作业已完成!");fclose(fp);goto label;default:printf("\nUnexpected job status .Please check you job file.");fprintf(fp,"\nUnexpected job status .Please check you job file.");fclose(fp);errorMessage();}switch(fitMethod) //不同分区管理方法的实现{case '1': order(&empty,0,0);break;case '2': order(&empty,0,1);break;case '3': order(&empty,1,0);break;case '4': order(&empty,1,1);break;}startAddress = allocate(&empty,size);if(startAddress != -1){insertUsedNode(&used,id,startAddress); //插入作业updateJobStatus(&jobs,id,1); //改变作业状态updateJobFile(jobs);}}label : ;break;case '3': //当选择3时if(memoryStartAddress < 0 || memorySize < 1){printf("\n\nBad memory allocated !\a");break;}do{int i;openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t作业完成(回收内存)");fclose(fp);if(showUsedList(jobs,used) == 0)break;openFile(&fp,"d:\\result.cl","a"); //打开文件fprintf(fp,"\n请从上面的作业中选择一个作业,输入作业名.\n输入-1来结束测试.");printf("\n请从上面的作业中选择一个作业,输入作业名.\n 输入-1来结束测试.");scanf("%d",&id);fprintf(fp,"%d\n",id);fclose(fp);if(id == -1)break;getJobInfo(jobs,id,&size,&status); //把作业放入内存if(status == 1) //作业状态为运行时{i = finishJob(&used,id,&startAddress);if(i){insertFreeNode(&empty,startAddress,size); //插入空闲分区updateJobStatus(&jobs,id,2); //改变作业状态updateJobFile(jobs);}}else{if(status == 0 || status == 2){if(status == 0)printf("\n作业不在内存中!");else printf("\n作业已完成!");}else{printf("\nUnexpected job status .\Please check you job file.");errorMessage();}}}while(1);break;case '4': //当选择4时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t显示空闲内存");fclose(fp);showFreeList(empty);break;case '5': //当选择5时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t显示已分配内存");fclose(fp);showUsedList(jobs,used);break;case '6': //当选择6时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t拼接碎片");fclose(fp);moveFragment(jobs,&empty,&used);break;case '7': //当选择7时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\tExit :(");fclose(fp);exit(0);default: printf("\n错误输入!");}}getch();}五.运行效果:1.运行EXE文件:2.首先要选择1,输入要分配内存的首地址,分区大小,输入作业的信息:3.按ENTER键后,选择分区管理算法:4.然后选择2,把作业放到内存:5.到此,用户就可以选择自己想要的操作功能,这里3为例:6.用户也可以选择其他功能,这里不作介绍。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
分页存储管理的模拟实验上机报告
页面管理的基本原理及方法:
各进程的虚拟空间被划分成若干个长度相等的页(page)。
页长的划分和内存外存之间的数据传输速度以及内存大小等有关。
页式管理还把内存空间也按也的大小划分为页面
(page frame)。
然后把页式虚拟地址与内存页面物理地址建立一一对应页表,并用相应的硬
件地址变换机构,来解决离散地址变换问题。
在作业或进程开始执行之前,把该作业或进程的程序段和数据全部装入内存的各个页
面中,并通过页表(page mapping table)和硬件地址变换机构实现虚拟地址到内存物理地址
的地址映射。
1. 内存页面分配
静态页面管理的第一步是为要求内存的作业或进程分配足够的页面。
系统依靠存储页面表,请求表及页表来完成内存的分配工作。
a. 页表
页表由页号与页面号组成。
如右图所示
为20k的进程来说,如果一个内存单元存放一个页表项,则只要分配给
该页表20个存储单元即可。
页式管理是每个进程至少拥有一个页表。
实验中对页表的定义如下(采用数组形式,数组下标表示页号,数
组单元存放与数组下标(页号)相应的页面号):int pagetable[100]
b.请求表(作业申请表)
请求表用来确定作业或进程的虚拟空间的各页在内存中的对应位置。
为了完成这个认为,系统必须知道每个作业或进程的页表起始地址(本实验中假定为0)和长度,以进行内存分
配和地址变换。
另外请求表中还包括每个作业或进程所要求的页面数。
请求表整个系统一张,
实验中对请求表的定义如下(采用结构体数组形式,并将页表也作为其中一个成员
(即域)):#define u 5
struct application_table
{
char name[8];/*作业名*/
int size;/*作业大小――即将上表中的请求页面数改用字节表示*/
int paddress;/*页表起始地址*/
int length;/*页表长度――以页面数表示*/
int state;/*内存的分配状态,以分配的用1表示,未分配的用0表示*/
int pagetable[100];/*页表,放在这里是为了方便虚地址转换及作业撤销的操作*/
}application[u];
c.存储页面表(本实验中采用位示图法)
位示图也是整个系统一张,它指出内存各页面是否已被分配出去,以及未分配页面的总数。
在内存中划分一块固定区域,每个单元的每个比特代表一个页面,如果该页面已被分配,则对应比特位置为1,否则为0。
本实验中采用二维数组(16*16)形式存储:
int graphic[16][16]={{0,0,0,1,1},{0,1,1,0,0},{0,0,0,0,1}} d. 分配算法
首先,将位示图初始化,可任选几个单元,
可全部初始化为0.
接着,键盘输入作业名(name)和作业大小(size),大小为1k, 所以将作业大小除以页面大小(1k),页面数(即页表长度),搜索空闲页面表看是否有n 返回”无法分配”,若有则开始设置页表,将作业名,址页表长度,状态置入请求表,起始地址为页表的第0
然后根据页表,搜索空闲页面表,填入页表中.
2. 地址变换
由地址分配方式得知,在一个作业或进程的页表中,连续的页号对应于不连续的页面号.做地址转换时,必须知道所要转换的虚地址(x)以及该虚地址所属作业名(由键盘输入,如有重名的作业,则顺序输出虚地址在各项作业中所对应的物理地址),查页表,对应页号y=x/1024,所求物理地址:
键盘输入所要撤销的作业名(如有重名,则都撤销),搜索作业申请表,每遇到作业名相同的,则
将作业大小及状态改为0(表示撤销),搜索页表,当作业名相同时,根据页表修改位示图中相应
4.功能模块的选择
实验中采用多分支选择语句(switch)来实现多种功能模块的选择,写在主程序中.。