存储器的分配与回收算法实现.docx
《存储器的分配与回收算法实现.docx》由会员分享,可在线阅读,更多相关《存储器的分配与回收算法实现.docx(23页珍藏版)》请在冰豆网上搜索。
存储器的分配与回收算法实现
姓名
学号
专业
班级
实验项目
实验二:
存储器的分配与回收算法实现
课程名称
操作系统
课程代码
0668036
实验时间
2011年11月04日
2011年11月08日
2011年12月02日
实验地点
软件实验室7-215
批改意见
成绩
教师签字:
【实验环境】Windows操作系统环境下的个人微机
【实验目的】
通过编写程序实现存储器的分配与回收算法,使学生进一步掌握存储器的分配与回收算法,加深对存储器分配的理解。
【实验要求】
学生应正确地设计有关的数据结构与各个功能模块,画出程序的流程图,编写程序,程序执行结果应正确。
【实验内容】
1 本实验是模拟操作系统的主存分配,运用可变分区的存储管理算法设计主存分配和回收程序,并不实际启动装入作业。
2 采用最先适应法、最佳适应法、最坏适应法分配主存空间。
3 当一个新作业要求装入主存时,必须查空闲区表,从中找出一个足够大的空闲区。
若找到的空闲区大于作业需要量,这时应把它分成二部分,一部分为占用区,剩余部分又成为一个空闲区。
4 当一个作业撤离时,归还的区域如果与其他空闲区相邻,则应合并成一个较大的空闲区,登在空闲区表中。
5 运行所设计的程序,输出有关数据结构表项的变化和内存的当前状态。
【实验原理及流程】
1、分配算法
1 最先适应法
FF算法要求空闲分区链以地址递增的次序链接。
在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。
若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。
2 最佳适应法
所谓“最佳”是指每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。
为了加速寻找,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一空闲分区链。
这样,第一次找到的能满足要求的空闲区,必然是最佳的。
3 最坏适应法
最坏适应分配算法要扫描整个空闲分区表或链表,总是挑选一个最大的空闲区分割给作业使用。
2、分配内存
1 算法原理:
系统应利用某种分配算法,从空闲分区链(表)中找到所需大小的分区。
设请求的分区大小为u.size,表中每个空闲分区的大小可表示为m.size。
若m.size-u.size≤size(size是事先规定的不再切割的剩余分区的大小),说明多余部分太小,可不再切割,将整个分区分配给请求者;否则(即多余部分超过size),从该分区中按请求的大小划分出一块内存空间分配出去,余下的部分仍留在空闲分区链(表)中。
然后,将分配区的首址返回给调用者。
2 流程图:
3、回收内存
1 算法原理:
当进程运行完毕释放内存时,系统根据回收区的首址,从空闲区链(表)中找到相应的插入点,此时可能出现以下四种情况之一:
(1)回收区与插入点的前一个空闲分区F1相邻接,见图4-8(a)。
此时应将回收区与插入点的前一分区合并,不必为回收分区分配新表项,而只需修改其前一分区F1的大小。
(2)回收分区与插入点的后一空闲分区F2相邻接,见图4-8(b)。
此时也可将两分区合并,形成新的空闲分区,但用回收区的首址作为新空闲区的首址,大小为两者之和。
(3)回收区同时与插入点的前、后两个分区邻接,见图4-8(c)。
此时将三个分区合并,使用F1的表项和F1的首址,取消F2的表项,大小为三者之和。
(4)回收区既不与F1邻接,又不与F2邻接。
这时应为回收区单独建立一新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置。
图4-8 内存回收时的情况
2 流程图:
【实验步骤、过程】
(1)部分源程序
(1)数据定义:
#definemSize5//不再切割的剩余分区大小
#definemMaxSize1024
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
//定义分区数据结构
typedefstructSubArea{
UINTArea_start;//分区始址
UINTArea_size;//分区大小
CStringArea_state;//状态位
SubArea*next;//后向指针
}SubArea;
//添加全局变量
SubArea*head;
intfree_count,busy_count;
intnItem;//当前选中行的索引
BOOLDistributing_tag=false;//表示还未进行内存分配操作
CStringJNAME;
UINTJSIZE;
UINTBUSY_SIZE;
(2)初始化操作面板:
BOOLCDEAL_STORAGE_NEWDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
//TODO:
Addextrainitializationhere
//添加自己的代码
//首先设定列表控件风格可以整行选中,并具有作业线
DWORDstyle=m_LIST_FREE.GetExtendedStyle();
m_LIST_FREE.SetExtendedStyle(style|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
DWORDstyle_1=m_LIST_BUSY.GetExtendedStyle();
m_LIST_BUSY.SetExtendedStyle(style_1|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
//以下为插入几个列的列标题
CRectrect;
m_LIST_FREE.GetClientRect(&rect);
intnColInterval=rect.Width()/7;
m_LIST_FREE.InsertColumn(0,"分区号",LVCFMT_LEFT,nColInterval*2);
m_LIST_FREE.InsertColumn(1,"分区始址/KB",LVCFMT_LEFT,nColInterval*2);
m_LIST_FREE.InsertColumn(2,"分区大小/KB",LVCFMT_LEFT,nColInterval*2);
m_LIST_FREE.InsertColumn(3,"状态",LVCFMT_LEFT,rect.Width()-nColInterval*6);
CRectrect_1;
m_LIST_BUSY.GetClientRect(&rect);
intnColInterval_1=rect_1.Width()/7;
m_LIST_BUSY.InsertColumn(0,"作业名称",LVCFMT_LEFT,nColInterval*2);
m_LIST_BUSY.InsertColumn(1,"分区始址/KB",LVCFMT_LEFT,nColInterval*2);
m_LIST_BUSY.InsertColumn(2,"分区大小/KB",LVCFMT_LEFT,nColInterval*2);
m_LIST_BUSY.InsertColumn(3,"状态",LVCFMT_LEFT,rect.Width()-nColInterval*6);
//初始化空闲分区链链首指针
head=newSubArea();
head->next=NULL;
//初始化列表控件计数变量
free_count=0;
busy_count=0;
//初始化列表控件
Initializing();
//初始化进度条
UpdateData(true);
BUSY_SIZE=0;
m_PROGRESS.SetRange(0,100);
m_PROGRESS.SetPos(0);
m_PERCENT.Format("%4.1f%%",0.0);
//初始化最大容量
m_MAXSIZE.Format("%d",mMaxSize);
UpdateData(false);
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
(3)功能实现:
voidCDEAL_STORAGE_NEWDlg:
:
OnBtnFormat()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
//提示用户确认格式化
if(MessageBox("您确定格式化吗?
","请确认",MB_YESNO)==IDYES)
{
Initializing();
}
}
//刷新列表控件
voidCDEAL_STORAGE_NEWDlg:
:
LISTALLITEMS()
{
//清空空闲分区列表控件
m_LIST_FREE.DeleteAllItems();
free_count=0;
CStringstrItem;
SubArea*temp;
temp=head->next;
while(temp)
{
strItem.Format(_T("%d"),free_count+1);
m_LIST_FREE.InsertItem(free_count,strItem);//首先插入一行,其中的字符可以任意,也可以为空
strItem.Format(_T("%d"),temp->Area_start);
m_LIST_FREE.SetItemText(free_count,1,strItem);//设置第二列数据,如此可以设置其它列的数据
strItem.Format(_T("%d"),temp->Area_size);
m_LIST_FREE.SetItemText(free_count,2,strItem);
m_LIST_FREE.SetItemText(free_count,3,temp->Area_state);
free_count++;//计数变量加1
temp=temp->next;
}
}
voidCDEAL_STORAGE_NEWDlg:
:
Initializing()
{
//清空列表控件
m_LIST_BUSY.DeleteAllItems();
m_LIST_FREE.DeleteAllItems();
//向空闲分区表中添加表项
CStringstrItem;
strItem.Format(_T("%d"),1);
m_LIST_FREE.InsertItem(0,strItem);//首先插入一行,其中的字符可以任意,也可以为空
strItem.Format(_T("%d"),0);
m_LIST_FREE.SetItemText(0,1,strItem);//设置第二列数据,如此可以设置其它列的数据
strItem.Format(_T("%d"),mMaxSize);
m_LIST_FREE.SetItemText(0,2,strItem);
m_LIST_FREE.SetItemText(0,3,_T("未分配"));
//创建分区对象
SubArea*subarea=newSubArea();
subarea->Area_start=0;
subarea->Area_size=mMaxSize;
subarea->Area_state="未分配";
//将创建的空闲分区对象链接到空闲链表中
head->next=subarea;
subarea->next=NULL;
//初始化进度条
BUSY_SIZE=0;
UINTpercent=(UINT)(BUSY_SIZE*1.0/mMaxSize*100);
m_PROGRESS.SetPos(percent);
m_PERCENT.Format("%4.1f%%",BUSY_SIZE*1.0/mMaxSize*100);
UpdateData(false);
//将内存分配标志置为false
Distributing_tag=false;
}
voidCDEAL_STORAGE_NEWDlg:
:
GetValue()
{
Distributing_tag=true;
//获取控件中的值
UpdateData(true);
JNAME=m_JNAME;
JSIZE=m_JSIZE;
}
//空闲分区链以地址递增的次序链接
voidCDEAL_STORAGE_NEWDlg:
:
Address_Up()
{
//按起始地址由小到大链接
intn=m_LIST_FREE.GetItemCount();
SubArea*p1,*p2;
for(inti=0;i{
p1=head->next;
for(intj=0;j{
p2=p1->next;
if(p1->Area_start>p2->Area_start)
{//交换
UINTk=p1->Area_size;
p1->Area_size=p2->Area_size;
p2->Area_size=k;
k=p1->Area_start;
p1->Area_start=p2->Area_start;
p2->Area_start=k;
}
p1=p1->next;
}
}
}
//分配内存
voidCDEAL_STORAGE_NEWDlg:
:
Distributing()
{
SubArea*search,*prior;
prior=head;
search=head->next;
intflag=0;//标记
for(;search;)
{
if(search->Area_size{
search=search->next;
prior=prior->next;
}
else
{
flag=1;
break;//已找到合适分区
}
}
if(flag){
//将JSIZE部分分配给作业
CStringstrItem;
m_LIST_BUSY.InsertItem(busy_count,m_JNAME);//首先插入一行,其中的字符可以任意,也可以为空
strItem.Format(_T("%d"),search->Area_start);
m_LIST_BUSY.SetItemText(busy_count,1,strItem);//设置第二列数据,如此可以设置其它列的数据
m_LIST_BUSY.SetItemText(busy_count,3,_T("已分配"));
//默认选中第一条记录
//m_LIST_BUSY.SetItemState(0,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
if(search->Area_size-JSIZE>mSize)
{
//剩余部分仍留在空闲分区链表中
search->Area_start+=JSIZE;
search->Area_size-=JSIZE;
strItem.Format(_T("%d"),JSIZE);
BUSY_SIZE+=JSIZE;
}
else
{//将该分区全部分配给作业
strItem.Format(_T("%d"),search->Area_size);
//直接将当前分区从空闲分区链表上摘除
prior->next=search->next;
BUSY_SIZE+=search->Area_size;
}
//刷新空闲分区列表控件
m_LIST_BUSY.SetItemText(busy_count,2,strItem);
busy_count++;//计数变量加1
LISTALLITEMS();
}
else{
MessageBox("未找到合适的分区,内存分配失败","提示",MB_ICONEXCLAMATION);
//格式化控件
m_JNAME.Format(_T(""));
m_JSIZE=0;
UpdateData(false);
return;
}
//格式化控件
m_JNAME.Format(_T(""));
m_JSIZE=0;
//刷新进度条
UINTpercent=(UINT)(BUSY_SIZE*1.0/mMaxSize*100);
m_PROGRESS.SetPos(percent);
m_PERCENT.Format("%4.1f%%",BUSY_SIZE*1.0/mMaxSize*100);
UpdateData(false);
}
voidCDEAL_STORAGE_NEWDlg:
:
OnFirstfit()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
GetValue();
if(JNAME.IsEmpty())
{
MessageBox("作业名称不能为空","提示",MB_ICONEXCLAMATION);
return;
}
if(JSIZE<=0)
{
MessageBox("请输入作业准确大小","提示",MB_ICONEXCLAMATION);
return;
}
//检索空闲分区链表
Address_Up();
Distributing();
}
//将空闲分区按容量从小到大排序
voidCDEAL_STORAGE_NEWDlg:
:
Min_to_Max_Sort()
{
intn=m_LIST_FREE.GetItemCount();
SubArea*p1,*p2;
for(inti=0;i{
p1=head->next;
for(intj=0;j{
p2=p1->next;
if(p1->Area_size>p2->Area_size)
{//交换
UINTk=p1->Area_size;
p1->Area_size=p2->Area_size;
p2->Area_size=k;
k=p1->Area_start;
p1->Area_start=p2->Area_start;
p2->Area_start=k;
}
p1=p1->next;
}
}
}
voidCDEAL_STORAGE_NEWDlg:
:
OnBestfit()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
GetValue();
if(JNAME.IsEmpty())
{
MessageBox("作业名称不能为空","提示",MB_ICONEXCLAMATION);
return;
}
//将空闲分区按容量从小到大排序
Min_to_Max_Sort();
Distributing();
}
//空闲分区按容量由大到小排序
voidCDEAL_STORAGE_NEWDlg:
:
Max_to_Min_Sort()
{
intn=m_LIST_FREE.GetItemCount();
SubArea*p1,*p2;
for(inti=0;i{
p1=head->next;
for(intj=0;j{
p2=p1->next;
if(p1->Area_sizeArea_size)
{//交换
UINTk=p1->Area_size;
p1->Area_size=p2->Area_size;
p2->Area_size=k;
k=p1->Area_start;
p1->Area_start=p2->Area_start;
p2->Area_start=k;
}
p1=p1->next;
}
}
}
voidCDEAL_STORAGE_NEWDlg:
:
OnWorstfit()
{
//TODO:
Addyourcontrolnotificationhandlercodehere
GetV