可变分区实验.docx

上传人:b****5 文档编号:5895784 上传时间:2023-01-02 格式:DOCX 页数:33 大小:64.41KB
下载 相关 举报
可变分区实验.docx_第1页
第1页 / 共33页
可变分区实验.docx_第2页
第2页 / 共33页
可变分区实验.docx_第3页
第3页 / 共33页
可变分区实验.docx_第4页
第4页 / 共33页
可变分区实验.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

可变分区实验.docx

《可变分区实验.docx》由会员分享,可在线阅读,更多相关《可变分区实验.docx(33页珍藏版)》请在冰豆网上搜索。

可变分区实验.docx

可变分区实验

可变分区实验

 

一、实验题目:

编写一个C程序,用char*malloc(unsignedsize)函数向系统申请一次内存空间(如size=1000,单位为字节),用循环首次适应法addr=(char*)lmalloc(unsignedsize)和lfree(unsignedsize,char*addr)模拟UNIX可变分区内存管理,实现对该内存区的分配和释放管理。

二、实验目的:

1.加深对可变分区的存储管理的理解;

2.提高用C语言编制大型系统程序的能力,特别是掌握C语言编程的难点:

指针和指针作为函数参数;

3.掌握用指针实现链表和在链表上的基本操作。

三、实验分析:

本实验采用循环首次适应法的方法来模拟UNIX的可变分区内存管理。

即对于系统中内存空闲区域表采用双向链表的形式存储。

当需要申请分配内存时,指向该区域表的指针搜索该表,在指针行走完一圈以前,一旦找到可以分配的空闲内存块即采用该空闲区域进行分配,并返回指向实际空闲区的指针。

此外,指向该循环链表的指针应当在没有操作的时候保持位置,完成操作后指向操作过的那个表项。

而释放内存也是基于基本相同的做法,但在释放后应当注意到相邻空闲区域的合并。

除了分配和释放这两个主要模块以外,系统还应当具备差错处理、初始化、释放退出等合理的功能。

四、概要设计:

本试验程序共10个模块,分别如下:

1.主程序模块main()

2.初始化系统模块x_Initialize()

3.命令处理模块x_Order()

4.错误命令处理模块x_ErrorOrder()

5.分配内存模块x_ApplyMem()

6.分配内存失败处理模块x_ErrorApply()

7.释放内存模块x_FreeMem()

8.释放内存失败处理模块x_ErrorFree()

9.打印空闲分区情况表模块x_PrintTable()

10.结束退出处理模块x_EndProgram()

概要设计结构图(StructureChart)如下:

程序基本流程图:

五、重要数据结构和变量说明:

1.内存空闲区域表单元(全局变量):

structmap{/*unitinthefreespacerecordtable*/

unsignedlongx_MemSize;

char*x_MemAddr;

structmap*x_TablePrev,*x_TableNext;

};

2.内存空闲区域表项指针(全局变量):

structmap*x_TableStart;

3.申请分配的内存总量(全局变量):

unsignedlongx_WholeMemSize=1024;

4.申请分配的内存块的首地址指针(全局变量)

char*x_Start;

5.模拟申请分配或释放的内存量

unsignedlongx_MemAmount;

6.返回的模拟内存分配的指针

char*x_Return;

7.要求释放的内存的起始相对地址

unsignedlongx_FreeAddr

六、主要模块详细设计:

1.初始化模块:

x_Initialize()

输入值:

返回值:

操作变量:

x_TableStart

调用模块:

打印表单模块x_PrintTable()

详细设计:

(伪代码)

申请内存空闲区域表单元;

建立内存空闲区域表并初始化;

输出提示信息;

打印该表单;

2.命令处理模块x_Order()

输入值:

返回值:

操作变量:

x_MemAmount,x_FreeAddr

调用模块:

x_ApplyMem(),x_FreeMem(),x_ErrorOrder(),x_PrintTable(),x_EndProgram()

详细设计:

for(;;)

{

给出提示信息,接受用户命令;

匹配用户命令;

if(是内存分配命令)

{

for(;读入字符是数字;)

将字符格式的内存区域量转变为整数形式的内存区域量;

if(接下来的字符不是结束符或者没有输入内存区域量)

x_ErrorOrder();

else/*输入命令符合格式*/

x_ApplyMem(x_MemAmount);

}

elseif(是释放内存命令)

{

for(;读入首批字符是数字;)

将字符格式的内存起始相对地址转变为整形;

if(接下来的字符不是空格)

x_ErrorOrder();

for(;读入字符是数字;)

将字符格式的内存量转变为整形;

if(接下来的字符不是结束符或没有输入内存量)

x_ErrorOrder();

else/*输入命令符合格式*/

x_FreeMem(x_FreeAddr,x_MemAmount);

}

elseif(是结束程序的命令)

{

x_EndProgram();

跳出;

}

else/*输入命令不合格式*/

{

x_ErrorOrder();

}

打印表单;

3.分配内存模块x_ApplyMem()

输入值:

x_MemAmount

返回值:

x_Return

操作变量:

x_TableStart,x_Return

调用模块:

x_ErrorApply()

详细设计:

if(空闲区域内存表不空)

{

do{

if(遍历链表指针指向的单元的空闲内存量大于申请量)

{

为x_Return赋值;

修改该链表单元的成员值;

if(剩余的空闲内存量为0)

{

if(该表只有一个单元了)

删除该单元,链表起始指针置空;

break;

else

删除该单元,妥善处理链表;

}

提示信息给出,返回指针;

}

移动遍历指针;

}while(遍历指针与起始指针不相等);

}

x_ErrorApply();

返回空指针;

4.释放内存模块x_FreeMem()

输入值:

x_MemAmount,x_FreeAddr

返回值:

操作变量:

x_TableStart

调用模块:

x_ErrorFree()

详细设计:

(伪代码)

初始化遍历指针等辅助变量;

if(要求释放的内存起始或终止地址越界)

记录错误;

else

{

if(原空闲内存区域表为空)

{

申请单元表项;

初始化该表项并建立该表;

记录操作成功;

}

else

{

do{

if(要求释放的内存起始地址已经存在于表中了)

记录错误;

移动遍历指针;

}while(遍历指针等于起始指针);

if(没有错误记录)

{

do{

if(前项地址小于后项地址)

{/*指针区域处于该表的折返处*/

if(要求释放的起始指针在两块之前或后,未临界)

{

申请新表项;

初始化并完善链表;

记录成功;

跳出;

}

elseif(要求释放的内存临界于前项)

{

修改前项的参数;

移动链表起始指针;

记录成功;

跳出;

}

elseif(要求释放的内存临界于后项)

{

修改后项的参数;

移动链表起始指针;

记录成功;

跳出;

}

}

elseif(前后项地址相同)

{/*只有一项*/

同样按以上三种情况处理;

else

{

if(释放区域在两项之中,且临界)

{

合并、修改前后项,并删除前项;

移动链表起始指针;

记录成功;

跳出;

}

elseif(释放区域与前项临界)

{

修改前项;

移动链表起始指针;

记录成功;

跳出;

}

elseif(释放区域与后项临界)

{

修改后项;

移动链表起始指针;

记录成功;

跳出;

}

elseif(释放区域在前后项之中,不临界)

{

申请新表项;

初始化并完善链表;

记录成功;

跳出;

}

}

}while(起始指针不等于遍历指针)

}

}

}

if(没有记录成功)

{

x_ErrorApply();

}

七、原程序代码

请参见F005-093-LiuXin.c,其中包含有测试数据及测试结果

八、测试方案及结果

在本实验中,我们采用白盒法的方法,即保证每一条支路都要至少走一遍。

因此,根据这个方法,我设计了如下的测试用例,并得到了如后所述的测试结果。

1.输入的命令不符合格式:

lmallod200

lmalloc23j3

lfres200200

lfree200

lfree3j2200

lfree2003j3

ent

理论输出均应为:

Yourinputisinvalid,pleaseinputinstandardway.

Thatis,lmalloc(lfree)size(address)(freesize)orend.

实际结果正确。

2.一次分配内存完毕,空闲内存分区表无剩余,再次要求分配内存,显示无内存信息。

lmalloc1024

lmalloc20

理论输出应为:

AllocatingSucceed!

TheGivenAddressis0

Notenoughmemory,pleasefreeorapplyforlessmemory!

实际结果正确。

3.释放内存(此时空闲表无节点,新建节点)

lfree200100

lfree100100(单节点,与后空间临界)

lmalloc100

lfree300100(单节点,与前空间临界)

lmalloc100

lfree5050(单节点,与该空间无关)

lmalloc50

lfree20050(单节点,与该空间无关)

lmalloc50

lmalloc100

lfree200100

lfree400100

lfree600100

lfree800100

lfree500100(连接前后两个节点)

lfree70050(连接前面的空间)

lfree75149(连接后面的空间)

lfree32050(与前后空间均无临界)

lfree100100(前后交界处,和前空间临界)

lfree900100(前后交界处,和后空间临界)

lfree100120(前后交界处,与前后空间均无临界)

lfree4040(前后交界处,与前后空间均无临界)

lfree102520(越界)

lfree1001000(越界)

lfree450500(和已空闲区域相冲突)

经测试结果均正确

4.申请内存(多个内存空闲区域情况下)

lmalloc40(需要删除节点)

lmalloc300(不删除节点)

经测试结果均正确

5.终止程序

在测试过程中,已经测试过了单节点情况下的退出,情况正常。

现在的测试文件中的退出为多节点情况下的退出,情况也正常。

经上述白盒法测试,暂时没有发现程序存在问题。

九、实验体会

1.本实验中的程序虽然不大,但还是有几个地方比较麻烦。

首先是命令的录入及识别问题。

采用scanf函数不仅有处理空格、回车之类键入的麻烦,而且我觉得也难以对命令输入的格式做出比较好的要求。

因此我采用了gets()函数,使用该函数的确不存在对于空格、回车之类输入的错误反应的问题。

但随之而来的麻烦是,如何将较好地字符型整数转化为整数型。

这一工作并没有什么难度,但比较繁琐。

经过我的处理之后的输入系统,基本上可以做到仅仅识别1种标准格式的输入,不在输入阶段产生问题。

2.系统的友好度的问题。

虽然说本程序的用途仅仅是仿真模拟unix内存分配,因此实际上考虑与用户之间交互的用好度并没有什么意义。

所以我一开始采用了分配内存实际物理地址返回,实际物理地址输入方能释放内存的方法,但显然这样非常的别扭,而且难以看懂。

于是后来我改用了物理的相对地址。

即以分配所得的内存首址作为相对地址0,以后的地址相应推的。

经过这样的改变以后,不仅对于测试来说变得简单明了,而且确实增加了系统交互的友好度。

我想如果设计的程序是和用户交互的话,那么这个方面要注意。

3.分类的重要性。

本程序另一大难点在于lfree函数中具体情况的处理。

因为释放的情况比较复杂,处理的方式也不太一样,而且还要兼顾到空闲区域表中的单元数量情况,因此比较麻烦。

我最初的程序设计中,分类并不够细致,没有将这个问题细化,所以曾经变成效率较低。

后来我重新对这一部分作了分析,划分了较多的情况,虽然比较繁琐,但应当说,程序变得明了清晰。

 

程序:

/*ThisprogramistosimulatethememoryallocatinginUnixusingthe"Firsttofit"algorithm.

Thereare9sub-functionsinthisprogram.

x_Initialize()----toinitializethememoryspaceandthetableusedtorecordtheconditionofmemoryallocating.

x_Order()---------todealwiththeordersgivedbyuser.

x_ErrorOrder()----todealwiththeerrortakingplaceinfunctionx_Order().

x_ApplyMem()------toapplyforthememoryspace.

x_ErrorApply()----todealwiththeerrortakingplaceinfunctionx_ApplyMem().

x_FreeMem()-------tofreethememoryspacegivenbyuser.

x_ErrorFree()-----todealwiththeerrortakingplaceinfunctionx_ErrorFree().

x_PrintTable()----tooutputthefreememoryconditiontabletoterminals.

x_EndProgram()----toendtheprogramandfreeallthememoryspaceoccupied.

Thisprogramisdevelopedon15th,SepbyXin,LiuF005ShanghaiJiaoTongUni.

F0055004129093LiuXin

*/

#include"stdio.h"

#include"math.h"

#include"stdlib.h"

#include"string.h"

/*Thispartistodefinethedatastuctureandvariablesusedintheprogram.*/

structmap{/*unitinthefreespacerecordtable*/

unsignedlongx_MemSize;

char*x_MemAddr;

structmap*x_TablePrev,*x_TableNext;

};

structmap*x_TableStart;/*Pointerofthefreespacetable*/

unsignedlongx_WholeMemSize=1024;/*Thesizeofavailablememory*/

char*x_Start;/*Thebeginningaddressofthefreespace*/

voidmain()

{

/*Thispartistodeclarethesub-functionsintheprogram.*/

voidx_Initialize();

voidx_Order();

voidx_ErrorOrder();

char*x_ApplyMem(unsignedlongx_MemAmount);

voidx_ErrorApply();

voidx_MemFree(unsignedlongx_FreeAddr,unsignedlongx_MemAmount);

voidx_ErrorFree();

voidx_PrintTable();

voidx_EndProgram();

/*Thispartistoapplyforthememoryspace.*/

x_Start=(char*)malloc(x_WholeMemSize);

 

/*Thispartistofinishthetaskoftheproblem.*/

x_Initialize(x_Start,x_WholeMemSize,x_TableStart);

x_Order(x_Start,x_TableStart);

}

voidx_Initialize()

{/*Toinitializethefreespacetable*/

charout[50]="Theinitializationworkhasbeenfinished!

\n";

x_TableStart=(structmap*)malloc(sizeof(structmap));

x_TableStart->x_MemAddr=x_Start;

x_TableStart->x_MemSize=x_WholeMemSize;

x_TableStart->x_TableNext=x_TableStart;

x_TableStart->x_TablePrev=x_TableStart;

puts(out);

x_PrintTable();

}

voidx_Order()

{

charx_UserOrder[30];/*tosaveuser'sorder*/

intx_MallocIdt=0;

intx_FreeIdt=0;

intx_EndIdt=0;/*above3toidentifyuser'sorder*/

inti=0;/*torecordthetimes*/

charx_Malloc[8]="lmalloc";

charx_Free[6]="lfree";

charx_End[4]="end\0";

for(;;)

{

/*Togettheinputofausera*/

printf("Command:

\\>");

gets(x_UserOrder);

x_MallocIdt=0;

x_FreeIdt=0;

x_EndIdt=0;

/*Toidentifytheorder*/

for(i=0;i<=7;i++)

{/*identifymalloca*/

if(x_Malloc[i]==x_UserOrder[i])

{

x_MallocIdt++;

}

}

for(i=0;i<=5;i++)

{/*identifyfreea*/

if(x_Free[i]==x_UserOrder[i])

{

x_FreeIdt++;

}

}

for(i=0;i<=3;i++)

{/*identifyenda*/

if(x_End[i]==x_UserOrder[i])

{

x_EndIdt++;

}

}

if(x_MallocIdt==8)

{/*Theorder"lmalloc"a*/

unsignedlongx_MemAmount=0;

i=8;

for(;((x_UserOrder[i]>='0')&&(x_UserOrder[i]<='9'));)

{/*Tosavethesizeofthespaceappliedfor)a*/

x_MemAmount=x_MemAmount*10+(x_UserOrder[i]-'0');

i++;

}

if((x_UserOrder[i]!

='\0')||(x_MemAmount==0))

{/*invalidinputa*/

x_ErrorOrder();

}

else

{

x_ApplyMem(x_MemAmount);

}

}

elseif(x_FreeIdt==6)

{/*Theorder"lfree"a*/

unsignedlongx_FreeAddr=0;

i=6;

for(;(x_UserOrder[i]>='0')&&(x_UserOrder[i]<='9');)

{/*Tosavethephysicalrelativeaddress)a*/

x_FreeAddr=x_FreeAddr*10+(x_UserOrder[i]-'0');

i++;

}

if(x_UserOrder[i]!

='')

{/*invalidinputa*/

x_ErrorOrder();

}

else

{/*addressisOKa*/

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1