操作系统段页式存储实验报告.docx
《操作系统段页式存储实验报告.docx》由会员分享,可在线阅读,更多相关《操作系统段页式存储实验报告.docx(18页珍藏版)》请在冰点文库上搜索。
![操作系统段页式存储实验报告.docx](https://file1.bingdoc.com/fileroot1/2023-6/27/1d482a4b-cb88-4fc0-a34d-b50d81935c16/1d482a4b-cb88-4fc0-a34d-b50d81935c161.gif)
操作系统段页式存储实验报告
一、指定的选题一一段页式存储管理
1课程设计题目分析
段式和页式存储管理各有优缺点,段页式存储管理系统,用分段的方法来分配和管理虚拟存储器,而用分页的方法来分配和管理主存。
既有段式系统便于实现段的共享,段的保护,动态链接和段的动态增长等一系列优点,又能像页式系统那样,很好地解决内存的外碎片问题。
段页式系统的基本原理,是分段和分页原理的组合。
即先将用户程序分为若干个段,再把每个段划分成若干页,并为每个段赋予一个段名。
在段页式系统中,地址结构由段号、段内页号、页内地址三部分组成。
在段页式系统中,为了便于实现地址变换,须配置一段表寄存器,存放段表始址和段长TL。
(1)
进行地址变换时,首先利用段号S,将它与段长TL进行比较,若S和段号来求出该段对应的段表项在段表中的位置,得到该段的页表始址;
(2)利用逻辑地址中的段内页号P,获得对应页的页表项位置,读出该页所在的物理块号b;
(3)用块号b和页内地址构成物理地址。
2数据结构及模块说明
2.1存储结构说明
在此段页式存储管理系统中,我们采用以下数据结构来存储数据,存储结构用结构体和结构体数组来实现:
2.1段表
段号s
状态flag
页表长度plen
页表始址psta
//段表
typedefstructStack
{
intnum;〃段号
intflag;//段状态
intplen;〃页表长度
intpsta;//页表始址
}Stack;
其中状态为1代表在内存,为0代表不在内存。
2.2页表
//页表
typedefstructPage
{
intnum;〃页号
intflag;//页状态,即是否在内存。
intblock;//该页对应的块号
}Page;
2.3数据区
简单起见,我们没有把内容初始化到每一个内存地址,只给出每个作业块的内容,并且用一串字符代
替。
typedefstructData
{
intnum;//内存的块数
stringstr;//对应数据块的作业内容,简化起见说明内容为一串字符。
}Data;
2.4快表
盹1=1.段号
段内页号
块号
〃快表
typedefstructQuick
{
intqs;〃快表段号
intqp;〃快表页号
intqb;〃快表段号
}Quick;
2.5段表寄存器
段表始址
段表长度
〃段表寄存器
typedefstructStare
{
intssta;//段表始址
intslen;〃段表长度
}Stare;
3程序流程图
4使用技术及实现功能
使用技术:
本实验使用VC++6.0平台,使用基本的控制台应用程序,单文档结构,主要数据结构是结构体间的关系。
打开VC++6.0建立一个空工程,然后简历C++源文件,根据数据结构编写代码。
实现功能:
从键盘输入进程及其各段大小,能实现空间的分配,回收,地址转换,能显示段表、页表及存储空间状态
5程序代码
#include
#include
#definenull"0"
usingnamespacestd;
//数据结构
〃快表
typedefstructQuick
{
intqs;〃快表块号
intqp;〃快表页号
intqb;〃快表段号
}Quick;
〃数据区,简单起见,只为每一个内储块写入内容,不具体到每一物理地址。
typedefstructData
{
intnum;//内存的块数
stringstr;//对应数据块的作业内容,简化起见说明内容为一串字符。
boolflag;//是否被分配,1为是,0为否
}Data;
//页表
typedefstructPage
{
intnum;〃页号
boolflag;//页状态,即是否在内存
intblock;//该页对应的块号}Page;
//段表typedefstructStack
{
intnum;//段号boolflag;//段状态intplen;〃页表长度
intpsta;//页表始址
}Stack;
〃段表寄存器
typedefstructStare
{
intssta;//段表始址intslen;〃段表长度
}Stare;
Stackss[10];//〃全局变量Starest;///////全局变量
Datawork[100];〃全局变量Quickqu;//////全局变量Pagepage[5][5];
boolmenuflag=0;
intbs;//内存大小
intbbs;//内存块大小
intblocknum;//总块数
intsums;//总段数
voidmenu();
voidstart();
voidchange();
voiddisplay_stack();
voiddisplay_page();
voiddisplay_flag();
voidrecycle();
intmain()
{
menu();
return0;
}
voidmenu()
{
cout«endl;
cout«"**
1、初始化表
*****"<cout«"**
2、物理地址转换
*****"<cout«"**
3、显示段表
*****"<cout«"**
4、显示页表
*****"<cout«"**
5、显示存储空间状态
*****"<cout«"**
6、回收
*****"<cout«"**
7、退出
*****"<cout«
请选择
**************"
<intmenu1;
cin>>menu1;
if(menu1!
=1&&menu1!
=2&&menu1!
=3&&menu1!
=4&&menu1!
=5&&menu
=6&&menu1!
=7)
{
coutvv"请输入正确的选项"<}
switch(menu1)
{
case1:
{
menuflag=1;
start();
break;}
case2:
{
if(menuflag==0)
{
coutvv"请初始化表"<}
change();
break;
}
case3:
{
if(menuflag==0)
{
coutvv"请初始化表"<menu();
}
display_stack();break;
}
case4:
{
if(menuflag==O)
{
cout«"请初始化表"<}
display_page();
break;
}
case5:
{
if(menuflag==0)
{
cout«"请初始化表"<}
display_flag();
break;
}
case6:
{
if(menuflag==0)
{
cout«"请初始化表"<menu();
recycle。
;
break;
}
case7:
break;
"/switch
}
voidstart()
{
coutvv"请输入内存大小(K)"«endl;
cin>>bs;
coutvv"请输入内存块的大小(k)"«endl;
cin>>bbs;
blocknum二bs/bbs;
coutvv"内存一共被分为"vvblocknum<<"块,每
块"vvbbscoutvv"请输入进程个数"<intpn;cin>>pn;
〃下面求所有进程的总段数和段表,并为每段创建页表
for(intpn1=0;pnlvpn;pn1++)
{
coutvv"请输入第"vvpnlvv"个进程的段数"vvendl;
intppn;
cin>>ppn;
sums+=ppn;
}
for(intss1=0;ss1vsums;ss1++)
{
coutvv"请输入第"vvsslvv"个段的:
段号,状态,页表长度,页表始址"<cin>>ss[ss1].num>>ss[ss1].flag>>ss
[ss1].plen>>ss[ss1].psta;
coutvv"请初始化第"vvsslvv"段的页表项,输入两个数
据页表状态和对应块号"<for(intsss1=0;sss1{
page[ss1][sss1].num二sssl;
coutvv"请输入该段第"vvssslvv"个页的页状
态和对应块号"vvendl;
cin>>page[ss1][sss1].flag>>page[ss1]
[sss1].block;
}
}
//初始化段表寄存器
coutvv"初始化段表寄存器的段表始址"<cin>>st.ssta;
st.slen=sums;
〃初始化内存中物理地址每一块的数据区
coutvv"简单起见,我们对物理地址的需要的块用字符串进
行简单的初始化,没有具体到每一物理地址"vvendl;
for(intbn二0;bnvblocknum;bn++)
intbnl;
,输入#时,
coutvv"请输入内存块号及内存块里的作业内容输入结
束"<cin>>bn1;
work[bn1].num二bnl;
cin>>work[bn1].str;
work[bn1].flag=1;
if(work[bn1].str==‘'#")
break;
}
//初始化快表
coutvv"简单起见,我们初始化快表只有一个"<>qu.qb>>qu.qp;
while(ss[qu.qb].flag!
=1||page[qu.qb]
[qu.qp].flag!
=1)
{
coutvv"该页不在内存请输入一页在内存中的
作为快表,请输入要作为快表的段号和页号"vvendl;
cin>>qu.qb>>qu.qp;
}
qu.qs=page[qu.qb][qu.qp].block;
menu();
}
voiddisplay_stack()
{
cout«"**段号状态页表长度页表始址*****"<for(intsn二0;sn{coutvv"**"<"<menu();
}
voiddisplay_page()
{
coutvv"**页号状态存储块号*****"<for(intsp1=0;sp1COUtVV"******第"VVspIVV"段的页表"<<"***************"vvend|;
coutvv"**
"<"<for(intsp2=0;sp2[sp2].flag<<""vvpage[sp1][sp2].block}
menu();
}
voiddisplay_flag()
{
coutvv"**块号状态*****"<for(intsf=0;sfvblocknum;sf++)
{
coutvv"**"vvsfvv""vvwork[sf].flagvv"
*****"<}
menu();
}
voidrecycle。
{
for(intsf=0;sf{
work[sf].flag=0;
work[sf].str=null;
}
menu();
}
voidchange()
{
coutvv"请输入要转化的逻辑地址,段号S,段内页号P,页内
偏移地
址d(B)"<intsnum,pnum,dnum;
cin>>snum>>pnum>>dnum;
//首先查快表
if(snum二二qu.qb&&pnum==qu.qp)
{
coutvv"快表命中"<<"对应块号
是"vvqu.qsvvendl;
cout«"该块中作业数据是"<[qu.qb][qu.qp].block].str<cout«"物理地址
是"<menu();
}
〃访问段表寄存器
else
{
coutvv"快表没有命中,访问段表寄存器,段
号等于段表始址加上偏移地址"<//intssnum;
//ssnum二st.ssta+snum;
if(snum>st.slen-1)
{
coutvv"越界中断"<menu();
}
〃访问段表
else
{
if(snum>=O&&snum<=st.slen-1)
{
//是否缺段
coutvv"段表有
效"<if(ss[snum].flag==O)
{
cout«"缺段中
断"<menu();
}
else
{
//查询页表,根据段号查
出页表始址,加上段内偏移页数,即得到页表项。
//缺页中断测试
if(pnum>ss
[snum].plen-1)
{
coutvv"缺页中断"<menu
();
}
else
{
if
(pnum>=O&&pnumv=ss[snum].plen-1)
{
if(page[snum][pnum].flag==O)
{
coutvv"缺页中断"<menu();
}else
{
coutvv"找到该页"<<"查询页表后对应块号
"<cout«"该块内存的数据是"<coutvv"转化得到的物理地址是:
"vvpage[snum]
[pnum].block*bbs*1024+dnum«endl;
menu();
}
}
}
}
}
}
}
}
6设计结论和心得
本次系统中,主要是利用简单的数据结构和VC的简单的控制台程序,采用自己定义数据模拟段页
式存储管理的方式,简单明快的是给用户一个功能菜单,进入菜单必须进行段表数据初始化,然后只要
不退出就可以进行各种地址转化测试,也可以重新初始化段表。
而数据结构部分,采用结构体数组比较
为了体现数据访问的
容易掌握的格式,是的查询过程简单化。
总的来说,利用简单的思想较为完整的模拟了段页式存储的各个步骤,甚至把快表也考虑了进去。
对于各种非法访问非常直观的指出非法原因。
真实性,我还简单的为内存中每一个作业快初始化了作业数据,找到物理块号后可以直接读出块的作业
内容。
体现的本程序的根本目的。
这个在程序中没有完整的表现出来,另外第一次程序中没有考虑页表越界中断,这是没有完整的把
握模拟系统中的各个环节造成的,为此要以自己写好的程序流程图为基础,考虑到每一步分支程序,尽
量用简单的方式把系统的各种功能模拟出来。
通过本次课程设计,加深了自己对书本知识的理解,通过亲自把模拟系统做成数据结构,更加直观真切的体会到段页式存储的基本思想,当然同时也对其他的存储知识加深了理解,同时锻炼了自己把
所学知识应用的实际视图里面的能力,做到学以致用,对计算机硬件里面的微观世界有了进一步的剖析。