《操作系统》存储管理实验报告.docx
《《操作系统》存储管理实验报告.docx》由会员分享,可在线阅读,更多相关《《操作系统》存储管理实验报告.docx(22页珍藏版)》请在冰豆网上搜索。
《操作系统》存储管理实验报告
—大学—学院实验报告
课程名称:
计算机操作系统实验名称:
存储管理实验实验日期:
班级:
姓名:
学号:
仪器编号:
XX
实验报告要求:
1.实验目的2.实验要求3.实验步骤4.程序清单5.运行情况6.流程图7.实验体会
1、实验目的
通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉虚存
管理的各种页面淘汰法。
通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。
2、实验要求
设计一个固定式分区分配的存储管理方案,并模拟实现分区的分配和回收过程。
可以假定每个作业都是批处理作业,并且不允许动态申请内存。
为实现分区的分配和回收,可以设
定一个分区说明表,按照表中的有关信息进行分配,并根据分区的分配和回收情况修改该表。
设计一个可变式分区分配的存储管理方案,并模拟实现分区的分配和回收过程。
对分区的管理法可以是下面三种算法之一:
首次适应算法;最坏适应算法;最佳适应算法。
编写并调试一个段页式存储管理的地址转换的模拟程序。
首先设计好段表、页表,然后给出若干个有一定代表性的地址,通过查找段表页表后得到转换的地
址。
要求打印转换前的地址,相应的段表,页表条款及转换后的地址,以便检查。
3、实验步骤
(1)理解实验要求,联系所学知识;
(2)根据要求编写调度算法;(3)编
写完整的实验代码并在VC++6.0环境下编译运行;(4)调试程序直至得出结
果。
4、程序清单
#include
#include#include
#include#defineNUM4
#definealloMemory(type)(type*)malloc(sizeof(type))structpartiTab
{
intno;
intsize;
intfirstAddr;
charstate;
}parTab[NUM];
typedefstructpartiTabPARTITAB;
typedefstructjcb{/*定义作业控制块JCB,部分信息省略*/
charname[10];//作业名
intsize;//作业大小
structjcb*link;//链指针
}JCB;
typedefstruct
{
JCB*front,*rear;
}jcbQue;
jcbQue*jcbReadyQue;
voidAllocateMemory(intsize);
voidcreateTab();
voidcheckTab();
voidrecycleMemory(inti);
voidAllocateMemory(intsize)
{
inti;
for(i=O;i{
PARTITABp=parTab[i];
if(p.state='N'&&p.size>size)
parTab[i].state二'Y';
else
\n");
printf("没有空闲分区,无法分配内存!
}
}
voidcreateTab()
{
inti;
for(i=1;i<=NUM;i++)
{
//getPartiTab(PARTITAB);
parTab[i-1].no二i;
parTab[i-1].size=20;
parTab[i-1].firstAddr=21;
parTab[i-1].state='N';
}
voidcheckTab()
{
inti;
printf("分区号\t大小\t起址\t状态\n");
for(i=0;i{
printf("%d\t",parTab[i].no);
printf("%d\t",parTab[i].size);
printf("%d\t",parTab[i].firstAddr);
printf("%c\t",parTab[i].state);
printf("\n");
}
}
voidrecycleMemory(inti)
{
parTab[i-1].state='N';
}
intmain(intargc,char*argv[])
{
inti;
createTab();
checkTab();
printf(”请按任意键继续:
\n");
getchar();
printf("每个分区装入一道作业:
\n");
for(i=0;iAllocateMemory((i+1)*3);
}
checkTab();
printf(”请按任意键继续:
\n");
getchar();
printf("假如一段时间后,其中一个作业结束,回收给它分配的分区(假如该作业在
第2分区)\n");
recycleMemory
(2);
checkTab();
printf(”请按任意键继续:
\n");
getchar();
printf("接着,从外存后备作业队列中选择一个作业装入该分区(假如该作业大小为
10)\n");
AllocateMemory(10);
checkTab();
#include#inelude
#include
#include
#definen10
#definem10
#defineminisize100struct
{
floataddress;
floatlength;
intflag;
}used_table[n];
struct
{
floataddress;
floatlength;
intflag;
}free_table[m];
voidallocate(charJ,floatxk)
{
inti,k;
floatad;
k=-1;
for(i=0;iif(free_table[i]」ength>=xk&&free_table[i].flag==1)if(k==-1||free_table[i]」engthif(k==-1)
{
printf("无可用空闲区\n");
return;
}
if(free_table[k].length-xk<=minisize)
{
free_table[k].flag=0;
ad二free_table[k].address;
xk=free_table[k]」ength;
}
else{
free_table[k].length二free_table[k]」ength-xk;ad=free_table[k].address+free_table[k].length;
}
i=0;
while(used_table[i].flag!
=0&&ii++;
if(i>二n)
printf("无表目填写已分分区,错误\n");
if(free_table[k].flag==O)free_table[k].flag=1;
else
{
free_table[k].length二free_table[k]」ength+xk;return;
}
}
else
{used_table[i].address二ad;used_table[i]」ength二xk;used_table[i].flag=J;
}
return;
}
voidreclaim(charJ)
{
inti,k,j,s,t;
floatS,L;
s=0;
while((used_table[s].flag!
二J||used_table[s].flag==0)&&sS++;
if(s>=n)
{
printf(”找不到该作业\n");
return;
}
used_table[s].flag=O;
S=used_table[s].address;
L=used_table[s]」ength;
j=-1;
k=-1;
i=0;
while(i{
if(free_table[i].flag==1)
{
if(free_table[i].address+free_table[i]」ength==S)k=i;
if(free_table[i].address==S+L)j=i;
}
i++;
}
if(k!
=-1)
if(j!
=-1)/*上邻空闲区,下邻空闲区,三项合并*/
free_table[k]」ength二free_table[j]」ength+free_table[k]」ength+L;free_table[j].flag=O;
}
else
/*上邻空闲区,下邻非空闲区,与上邻合并*/
free_table[k].length二free_table[k]」ength+L;
elseif(j!
=-1)/*上邻非空闲区,下邻为空闲区,与下邻合并*/
{
free_table[j].address=S;
free_table[j].length二free_table[j]」ength+L;
}
else/*上下邻均为非空闲区,回收区域直接填入*/
{
/*在空闲区表中寻找空栏目*/
t=0;
while(free_table[t].flag==1&&tt++;
if(t>=m)/*空闲区表满,回收空间失败,将已分配表复原*/
{
printf("主存空闲表没有空间,回收空间失败\n");
used_table[s].flag二J;
return;
}
free_table[t]」ength二L;
free_table[t].flag=1;
}return;
}/*主存回收函数结束*/
intmain()
{
printf("\n\n\t\t
********************************************
*\t\t\n");
printf("\t\t\t\t实验三存储管理实验\n”);
printf("\n\t\t\t可变式分区分配(最佳适应算法)\n");
inti,a;
floatxk;
charJ;
/*空闲分区表初始化:
*/
free_table[0].address=10240;/*
其余空闲分区表项未被使用*/
free_table[0].flag=1;/*for(i=1;i*/for(i=0;i(1)
退出\n");
printf("功能选择项:
\n1。
显示主存\n2。
分配主存\n3。
回收主存\n4
printf("请选择相应功能1--4:
");
seanf("%d",&a);
switch(a)
{
case4:
exit(O);/*a=4程序结束*/
case2:
/*a=2分配主存空间*/
printf("输入作业名J和作业所需空间xk:
");
seanf("%*c%c%f",&J,&xk);
allocate(J,xk);/*分配主存空间*/
break;
case3:
/*a=3回收主存空间*/
printf("输入要回收分区的作业名");
scanf("%*c%c",&J);
reclaim(J);/*回收主存空间*/
break;
case1:
/*a=1显示主存情况*/
/*输出空闲区表和已分配表的内容*/
printf("输出空闲区表:
\n起始地址分区长度标志\n");
for(i=0;iprintf("按任意键,输出已分配区表\n");
getch();
printf("输出已分配区表:
\n起始地址分区长度标志\n");
for(i=0;iif(used_table[i].flag!
=O)
printf("%6.0f%9.0f%6c\n",used_table[i].address,used_table[i]」ength,
used_table[i].flag);
else
printf("%6.0f%9.0f%6d\n",used_table[i].address,used_table[i]」ength,
used_table[i].flag);
break;
default:
printf("没有该选项\n");
}/*case*/
}/*while*/
return1;
}
#include
#include
usingnamespacestd;
typedefstructQuick
{
intqs;//快表段号
intqp;〃快表页号
intqb;〃快表段号
}Quick;
typedefstructData
{
intnum;//内存的块数
stringstr;//对应数据块的作业内容,简化起见说明内容为一串字符
}Data;
//页表
typedefstructPage
{
intnum;〃
页号
intflag;//
页状态,即是否在内存
intblock;//
该页对应的块号
}Page;
typedefstructStack
{
intnum;〃
段号
intflag;//
段状态
intplen;//
页表长度
intpsta;//
页表始址
}Stack;
//段表寄存器
typedefstructStare
{
intssta;//段表始址
intslen;//段表长度
}Stare;
Stackss[10];//〃全局变量
Starest;///////全局变量
Datawork[20];〃全局变量
Quickqu;//////全局变量
Pagepage[5][5];
boolmenuflag=0;
intbbs;〃内存块大小
intbs;//内存大小
voidmenu();
voidstart();
voidchange();
intmain()
{
menu();
return0;
voidmenu()
cout*********************************************
\t\t"<dl;
cout<<"\t\t\t\t
实验三存储管理实验"<
cout«"\n\t\t\t
段页式存储管理的地址转换的模拟程序"<cout<<"\t\t*
********************************************"
<cout«"请选择:
"<cout«endl;
cout«"1、初始化表"<cout«"2、物理地址转换"<coutvv"3、退出"<intmenu1;
cin>>menu1;
if(menu1!
=1&&menu1!
=2&&menu1!
=3)
{
coutvv"请输入正确的选项"<menu();
}
switch(menu1)
{
case1:
{
menuflag=1;
start();
break;
}
case2:
if(menuflag==O)
{
cout«"请初始化表"<menu();
}
change();
break;
}
case3:
return;
"/switch
}
voidstart()
{
cout«"请输入内存大小(K)"«endl;
cin>>bs;
cout«"请输入内存块的大小(k)"«endl;
cin>>bbs;
intblocknum;
blocknum二bs/bbs;
cout«"内存一共被分为"《blocknum<<"块,每块"<"vvbsintpn;
cin>>pn;
//下面求所有进程的总段数和段表,并为每段创建页表
intsums=O;
for(intpn1=0;pn1{
cout«"请输入第"<intppn;
cin>>ppn;
sums+=ppn;
}
for(intss1=0;ss1{
COUt«"请输入第"VVSSlVV"个段表数据:
段号,状态,页表长度,页表始
址"<cin>>ss[ss1].num>>ss[ss1].flag»ss[ss1].plen>>ss[ss1].psta;
COUt«"请初始化第"<号"<for(intsss1=0;sss1{
page[ss1][sss1].num二sss1;
Cout«"请输入该段第"<cin>>page[ss1][sss1].flag»page[ss1][sss1].block;
//初始化段表寄存器
coutvv"初始化段表寄存器的段表始址"<cin>>st.ssta;
st.slen=sums;
//初始化内存中物理地址每一块的数据区
COUt«"简单起见,我们对物理地址的每一块用字符串进行简单的初始化,没有
具体到每一物理地址"<for(intbn=0;bnvblocknum;bn++)
{
work[bn].num二bn;
coutvv"请输入第"<cin>>work[bn].str;
}
//初始化快表
coutvv"简单起见,我们初始化快表只有一个"<coutvv"请输入要作为快表的段号和页号"<cin>>qu.qb»qu.qp;
while(ss[qu.qb].flag!
=1||page[qu.qb][qu.qp].flag!
=1)
{
coutvv"该页不在内存请输入一页在内存中的作为快表,请输入要作为快表
cin>>qu.qb»qu.qp;
qu.qs二page[qu.qb][qu.qp].block;
menu();
}
voidchange()
{
COUtVV"请输入要转化的逻辑地址,段号S,段内页号p,页内偏移地址
d(B)"«endl;
intsnum,pnum,dnum;
cin>>snum>>pnum>>dnum;
//首先查快表
if(snum二二qu.qb&&pnum二二qu.qp)
{
cout«"快表命中"<<"对应块号是"vvqu.qsvvendl;
cout«"该块中作业数据
"vvwork[page[qu.qb][qu.qp].block].strvcout«"物理地址是"<menu();
}
//访问段表寄存器
else
{
Cout«"快表没有命中,访问段表寄存器,段号等于段表始址加上偏移地址
intssnum;
ssnum二st.ssta+snum;
if(ssnum>st.slen-1)
{
cout«"越界中断"<menu();
}
//访问段表
else
{
if(ssnum>=O&&ssnumv=st.slen-1)
{
//是否缺段
cout«"段表有效"<if(ss[ssnum].flag==0)
{
cout«"缺段中断"<menu();
}
else
{
//查询页表,根据段号查出页表始址,加上段内偏移页数,
即得到页表项。
//缺页中断测试
if(pnum>ss[ssnum].plen-1)
menu();
}
else
{
if(pnum>=O&&pnumv=ss[ssnum].plen-1)
{
if(page[ssnum][pnum].flag==0)
{
cout«"缺页中断"<menu();
}
else
{
COUt«"找到该页"<<"查询页表后对应块号
"<COUt«"该块内存的数据是
"<COut«"转化得到的物理地址是:
"<menu();
}
}
}
}
}
}
5、运行情况
按提示操作,直至程序运行完毕,即可得结果。
6、流程图
7、心得体会
通过这次实验,我懂得了存储管理分配和回收的一些简单算法的实现。
对于实验
教
师
签
名
过程中遇到的问题,通过上网查找相关资料以及研读课本上的理论知识,都一一得到了解决。
同时,实验过程中我还掌握了用高级语言编写和调试管理程序的方法,加深了对存储管理各种算法的概念及存储管理算法的理解,加深了对段页式存储管理的地址转换的理解。
多次实验下来最大的感受就是:
实践出真知。
只有把所学知识付诸实践才能真正地掌握知识。
优
教师评价
秀