北京邮电大学操作系统实验内存Word格式文档下载.docx
- 文档编号:22491816
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:42
- 大小:494.10KB
北京邮电大学操作系统实验内存Word格式文档下载.docx
《北京邮电大学操作系统实验内存Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《北京邮电大学操作系统实验内存Word格式文档下载.docx(42页珍藏版)》请在冰豆网上搜索。
(2)将指令序列变换为页地址流
设:
页面大小为1K;
用户内存容量4页到32页;
用户虚存容量为32K。
在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:
第0条-第9条指令为第0页(对应虚存地址为[0,9])
第10条-第19条指令为第1页(对应虚存地址为[10,19])
………………………………
第310条-第319条指令为第31页(对应虚存地址为[310,319])
按以上方式,用户指令可组成32页。
三项目分析
3.1对于BuddySystem
BuddySystem是一种经典的内存管理算法。
在Unix和Linux操作系统中都有用到。
其作用是减少存储空间中的空洞、减少碎片、增加利用率。
避免外碎片的方法有两种:
a.利用分页单元把一组非连续的空闲页框映射到非连续的线性地址区间。
b.开发适当的技术来记录现存的空闲连续页框块的情况,以尽量避免为满足对小块的请求而把大块的空闲块进行分割。
基于下面三种原因,内核选择第二种避免方法:
a.在某些情况下,连续的页框确实必要。
b.即使连续页框的分配不是很必要,它在保持内核页表不变方面所起的作用也是不容忽视的。
假如修改页表,则导致平均访存次数增加,从而频繁刷新TLB。
c.通过4M的页可以访问大块连续的物理内存,相对于4K页的使用,TLB未命中率降低,加快平均访存速度。
Buddy算法将所有空闲页框分组为10个块链表,每个块链表分别包含1,2,4,8,16,32,64,128,256,512个连续的页框,每个块的第一个页框的物理地址是该块大小的整数倍。
如,大小为16个页框的块,其起始地址是16*2^12的倍数。
例,假设要请求一个128个页框的块,算法先检查128个页框的链表是否有空闲块,如果没有则查256个页框的链表,有则将256个页框的块分裂两份,一份使用,一份插入128个页框的链表。
如果还没有,就查512个页框的链表,有的话就分裂为128,128,256,一个128使用,剩余两个插入对应链表。
如果在512还没查到,则返回出错信号。
回收过程相反,内核试图把大小为b的空闲伙伴合并为一个大小为2b的单独块,满足以下条件的两个块称为伙伴:
a.两个块具有相同的大小,记做b。
b.它们的物理地址是连续的。
c.第一个块的第一个页框的物理地址是2*b*2^12的倍数。
该算法迭代,如果成功合并所释放的块,会试图合并2b的块来形成更大的块。
为了模拟BuddySystem算法,我采用了数的数据结构,并使用了结构体,来记录各项数据与标记,虽然不是真正的操作系统使用的方法,但成功模拟了插入和回收的过程。
在回收时我采用物理上的合并——即删除实际的物理节点,释放空间。
然而实际中可能根据需要仅仅是删除了标记项,使之标记成没用过的,从而避免了合并,会提高下一次的插入操作。
碎片百分比=碎片总大小/总内存大小
3.2页式存储管理中页面置换算法模拟设计
页式虚拟存储器实现的一个难点是设计页面调度(置换)算法,即将新页面调入内存时,如果内存中所有的物理页都已经分配出去,就要按某种策略来废弃某个页面,将其所占据的物理页释放出来,供新页面使用。
页面替换算法主要用于如下几个地方:
(1)虚拟存储器中,主存页面(或程序段)的替换。
(2)Cache中的块替换。
(3)虚拟存储器的快慢表中,快表的替换。
(4)虚拟存储器中,用户基地址寄存器的替换。
在虚拟存储器中常用的页面替换算法有如下几种:
(1)最优替换算法,即OPT算法(OPTimalreplacementalgorithm)。
上面介绍的几种页面替换算法主要是以主存储器中页面调度情况的历史信息为依据的,它假设将来主存储器中的页面调度情况与过去一段时间内主存储器中的页面调度情况是相同的。
显然,这种假设不总是正确的。
最好的算法应该是选择将来最久不被访问的页面作为被替换的页面,这种替换算法的命中率一定是最高的,它就是最优替换算法。
要实现OPT算法,唯一的办法是让程序先执行一遍,记录下实际的页地址流情况。
根据这个页地址流才能找出当前要被替换的页面。
显然,这样做是不现实的。
因此,OPT算法只是一种理想化的算法,然而,它也是一种很有用的算法。
实际上,经常把这种算法用来作为评价其它页面替换算法好坏的标准。
在其它条件相同的情况下,哪一种页面替换算法的命中率与OPT算法最接近,那么,它就是一种比较好的页面替换算法。
(2)先进先出算法,即FIFO算法(First-InFirst-Outalgorithm)。
这种算法选择最先调入主存储器的页面作为被替换的页面。
它的优点是比较容易实现,能够利用主存储器中页面调度情况的历史信息,但是,没有反映程序的局部性。
因为最先调入主存的页面,很可能也是经常要使用的页面。
(3)最久没有使用算法,即LRU算法(LeastRecentlyUsedalgorithm)。
这种算法把近期最久没有被访问过的页面作为被替换的页面。
它把LFU算法中要记录数量上的"
多"
与"
少"
简化成判断"
有"
无"
,因此,实现起来比较容易。
(4)近期最少使用算法,即LFU算法(LeastFrequentlyUsedalgorithm)。
这种算法选择近期最少访问的页面作为被替换的页面。
显然,这是一种非常合理的算法,因为到目前为止最少使用的页面,很可能也是将来最少访问的页面。
该算法既充分利用了主存中页面调度情况的历史信息,又正确反映了程序的局部性。
但是,这种算法实现起来非常困难,它要为每个页面设置一个很长的计数器,并且要选择一个固定的时钟为每个计数器定时计数。
在选择被替换页面时,要从所有计数器中找出一个计数值最大的计数器。
因此,通常采用如下一种相对比较简单的方法。
(5)最近未使用法(NoUsedRecently)
缺页中断率=缺页中断次数/总的页面引用次数*100%
四问题实现及运行结果
4.1对于BuddySystem
4.1.1数据结构
节点的结构
structmemory_node
{
intremain_max;
//还能分配的最大空间
intuse;
//已用掉的大小
inttotal;
intpid;
//标记进程号
intflag;
//是否分裂,即是否有孩子,0为未分配
structmemory_node*left;
structmemory_node*right;
};
typedefstructmemory_node*NODE;
4.1.2全局变量
#defineInital1024//初始时的总内存
NODEroot=(memory_node*)malloc(1*sizeof(memory_node));
//根节点
intchip=0;
//记录总的碎片大小
intchip_num=0;
//记录碎片的数量
4.1.3函数定义
函数名称
实现功能
voidinital(NODEnode,intnum)
初始化节点
intmemory_alloc(intitem,NODEnode,intpid)
伙伴算法的分配
voidLprintf(void)
输出格式控制
voidpreoder_print(NODEnode)
中序遍历打印出所有的叶节点
intmemory_merge(intpid,NODEnode)
伙伴算法的合并
4.1.4依次插入item=129pid=0item=267pid=1的示意图
4.1.5删除pid=0的过程图
4.1.6在window下运行的结果
插入10个随机的值并分配结果如下,其中表中没有pid的为插入不成功的
释放随机的10个pid,找不到的不释放
4.1.7在linux下
生成两个线程,使用mutex为锁,当一个在插入时,另一个不能释放,达到互斥的效果
新增如下变量:
pthread_mutex_tmutex;
//信号量mutex
intpro_speed=4,con_speed=2;
//可以设定两者速度
新增函数:
void*producer(void*param)//插入的线程函数
void*consumer(void*param)//释放的线程函数
首先:
编译链接运行
显示如下:
4.1.7源代码见附录(linux下的)
4.2页式存储管理中页面置换算法模拟设计
4.2.1数据结构
(1)页面类型
typedefstruct
intpn,;
//页号
intpn;
//面号
intcounter;
//一个周期内访问该页面的次数
inttime;
//time为访问时间
}pl-type;
(2)页面控制结构
Pfc_struct
intpn,pfn;
structpfc_struct*next;
}
typedefstructpfc_structpfc_type;
pfc_typepfc_struct[total_vp];
//pfc[total_vp]定义用户进程虚页控制结构
pfc_type*freepf_head;
//空页面头的指针
pfc_type*busypf_head;
//忙页面头的指针,
pfc_type*busypf_tail;
//忙页面尾的指针.
4.2.2变量定义
inta[total_instruction]
指令流数据组
intpage[total_instruction]
每条指令所属的页号
intoffset[total_instruction]
每页装入10条指令后取模运算页号偏移值
inttotal_pf
用户进程的内存页面数
intdisaffect
页面失效次数
4.2.3函数定义
voidLprintf(void)
格式控制
voidinitialize(inttotal_pf)
初始化相关数据结构
voidFIFO(inttotal_pf)
先进先出法(FisrtInFirstOut)
voidLRU(inttotal_pf)
最近最久未使用(LeastRecentlyUsed)
voidOPT(inttotal_pf)
最佳置换算法(Optimal)
voidLFU(inttotal_pf)
最不经常使用法(LeastFrequentlyUsed)
voidNUR(inttotal_pf)
最近未使用法(NoUsedRecently)
4.2.4流程图
(1)页面调度模拟算法流程示例图
(2)FIFO和LRU调度模拟算法示例图
4.2.5运行实例
4.2.6数据分析
对各个算法进行统计分析得到如下表,前五个是单独的,最后一个合到一个图
由图表可知:
以OPT算法的命中率最高,NUR算法次之,其次是LFU算法和LRU算法,最后是FIFO算法。
五所遇到问题及实验感悟
实验中对于伙伴算法编写释放函数时,一开始总是出现错误。
后经过检查,发现原来是释放节点的判断函数出现了错误,进而使得最后总是全部释放完。
在后来将其移植到linux下是也遇到了一些小问题,如编译不过、打印错误等等,不过最终都解决了。
通过对上述两个实验的实际操作,加深了对伙伴算法、也米娜
六附录:
源代码
6.1Buddy算法
#include<
stdio.h>
stdlib.h>
pthread.h>
semaphore.h>
time.h>
#defineInital1024
structmemory_node
structmemory_nodep={0,0,0,0,0,NULL,NULL};
NODEroot=NULL;
intproc_num=0;
/*
Name:
voidinital(NODEnode,intnum)
Achieve:
初始化节点
*/
{
node->
remain_max=num;
total=num;
use=0;
flag=0;
pid=-1;
left=NULL;
right=NULL;
}
intmemory_alloc(intitem,NODEnode)
伙伴算法的分配
intnum,i,temp1,temp2;
if(item>
remain_max)
{
printf("
*****无足够内存,请等待(执行下一条)***\n"
);
returnnode->
remain_max;
if(node->
flag==0)//如果还没有分裂
remain_max/2)//如果item大于当前容量的1/2
remain_max=0;
node->
use=item;
pid=pid;
returnnode->
remain_max;
else//如果item小于当前容量的1/2,则应分裂节点
NODEl=(memory_node*)malloc(1*sizeof(memory_node));
NODEr=(memory_node*)malloc(1*sizeof(memory_node));
num=node->
remain_max/2;
inital(l,num);
//初始化左孩子
inital(r,num);
//初始化右孩子
left=l;
right=r;
//所能使用的最大值为node->
remain_max/2
flag=1;
//标记为1,表明是非叶节点
i=memory_alloc(item,l,pid);
//分配给左孩子
returnnum;
else//如果已分裂
temp1=node->
left->
temp2=node->
right->
if(temp1<
=temp2)//若左边的remain小于右边的remain
if(item<
=temp1)//如果item小于左边的
{
i=memory_alloc(item,node->
left,pid);
node->
remain_max=temp2;
//当前的remain=temp2
returntemp2;
}
else//如果item大于左边的
right,pid);
//分配给右孩子
if(i>
temp1)//当前的remain等于左右孩子remain的最大值
{
remain_max=i;
returni;
}
else
remain_max=temp1;
returntemp1;
else//若左边的remain大于右边的remain
=temp2)//如果item小于右边的
else
=temp2)
voidLprintf(void)
输出格式控制
inti,j;
|"
for(i=1;
i<
=7;
i++)
for(j=1;
j<
=9;
j++)
-"
if(i!
=7)
+"
|\n"
voidpreoder_print(NODEnode)
中序遍历打印出所有的叶节点
flag==0)
{
total!
=node->
chip_num++;
chip+=node->
total-node->
use;
|%-9d"
node->
total);
pid);
remain_max);
use);
flag);
chip);
chip_num);
Lprintf();
preoder_print(node->
left);
right);
voidmemory_merge()
伙伴算法的合并
intnum=node->
total;
inttemp1,temp2;
left==NULL&
&
node->
right==NULL)
pid==pid)
inital(node,num);
return-2;
return-1;
temp1=memory_merge(pid,node->
if(temp1==-2)
remain_max!
=num/2)
remain_max=node->
elseif(node->
free(node->
temp2=memory_merge(pid,node->
if(temp2==-1)
return-1;
flag==0
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北京邮电 大学 操作系统 实验 内存