1、可变分区实验可变分区实验一、 实验题目:编写一个C程序,用char *malloc(unsigned size)函数向系统申请一次内存空间(如size=1000,单位为字节),用循环首次适应法addr = (char *) lmalloc (unsigned size) 和lfree (unsigned size , char * addr)模拟UNIX可变分区内存管理,实现对该内存区的分配和释放管理。二、 实验目的:1 加深对可变分区的存储管理的理解;2 提高用C语言编制大型系统程序的能力,特别是掌握C语言编程的难点:指针和指针作为函数参数;3 掌握用指针实现链表和在链表上的基本操作。三、
2、实验分析:本实验采用循环首次适应法的方法来模拟UNIX的可变分区内存管理。即对于系统中内存空闲区域表采用双向链表的形式存储。当需要申请分配内存时,指向该区域表的指针搜索该表,在指针行走完一圈以前,一旦找到可以分配的空闲内存块即采用该空闲区域进行分配,并返回指向实际空闲区的指针。此外,指向该循环链表的指针应当在没有操作的时候保持位置,完成操作后指向操作过的那个表项。而释放内存也是基于基本相同的做法,但在释放后应当注意到相邻空闲区域的合并。除了分配和释放这两个主要模块以外,系统还应当具备差错处理、初始化、释放退出等合理的功能。四、 概要设计:本试验程序共10个模块,分别如下:1. 主程序模块 ma
3、in( )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( )概要设计结构图(Structure Chart)如下:程序基本流程图:五、 重要数据结构和变量说明:1 内存空闲区域表单元(
4、全局变量):struct map /*unit in the free space record table*/ unsigned long x_MemSize; char *x_MemAddr; struct map *x_TablePrev,*x_TableNext;2 内存空闲区域表项指针(全局变量):struct map *x_TableStart;3 申请分配的内存总量(全局变量):unsigned long x_WholeMemSize=1024;4 申请分配的内存块的首地址指针(全局变量)char *x_Start;5 模拟申请分配或释放的内存量unsigned long x_M
5、emAmount;6 返回的模拟内存分配的指针char *x_Return;7 要求释放的内存的起始相对地址unsigned long x_FreeAddr六、 主要模块详细设计:1 初始化模块:x_Initialize( )输入值: 无返回值: 无操作变量: x_TableStart 调用模块: 打印表单模块 x_PrintTable( )详细设计: (伪代码)申请内存空闲区域表单元;建立内存空闲区域表并初始化;输出提示信息;打印该表单;2 命令处理模块x_Order( )输入值: 无返回值: 无操作变量: x_MemAmount,x_FreeAddr调用模块: x_ApplyMem( ),
6、x_FreeMem( ),x_ErrorOrder(),x_PrintTable( ),x_EndProgram( )详细设计:for(;) 给出提示信息,接受用户命令; 匹配用户命令; if(是内存分配命令) for(;读入字符是数字;)将字符格式的内存区域量转变为整数形式的内存区域量; if(接下来的字符不是结束符或者没有输入内存区域量) x_ErrorOrder( ); else /*输入命令符合格式*/ x_ApplyMem( x_MemAmount ); else if(是释放内存命令) for(;读入首批字符是数字;) 将字符格式的内存起始相对地址转变为整形; if(接下来的字符不
7、是空格) x_ErrorOrder( ); for(;读入字符是数字;) 将字符格式的内存量转变为整形; if(接下来的字符不是结束符或没有输入内存量) x_ErrorOrder( ); else /*输入命令符合格式*/ x_FreeMem( x_FreeAddr , x_MemAmount ); else if(是结束程序的命令) x_EndProgram( ); 跳出; else /*输入命令不合格式*/ x_ErrorOrder( ); 打印表单;3 分配内存模块x_ApplyMem( )输入值: x_MemAmount返回值: x_Return操作变量: x_TableStart,x
8、_Return 调用模块: x_ErrorApply( )详细设计: if(空闲区域内存表不空) do if(遍历链表指针指向的单元的空闲内存量大于申请量) 为x_Return赋值; 修改该链表单元的成员值; if(剩余的空闲内存量为0) if(该表只有一个单元了) 删除该单元,链表起始指针置空; break; else 删除该单元,妥善处理链表; 提示信息给出,返回指针; 移动遍历指针; while(遍历指针与起始指针不相等);x_ErrorApply( );返回空指针;4 释放内存模块x_FreeMem( )输入值: x_MemAmount , x_FreeAddr返回值: 无操作变量:
9、x_TableStart调用模块: x_ErrorFree( )详细设计: (伪代码)初始化遍历指针等辅助变量;if(要求释放的内存起始或终止地址越界) 记录错误;else if(原空闲内存区域表为空) 申请单元表项; 初始化该表项并建立该表; 记录操作成功; else do if(要求释放的内存起始地址已经存在于表中了) 记录错误; 移动遍历指针; while(遍历指针等于起始指针); if(没有错误记录) do if(前项地址小于后项地址) /*指针区域处于该表的折返处*/ if(要求释放的起始指针在两块之前或后,未临界) 申请新表项;初始化并完善链表;记录成功;跳出; else if(要
10、求释放的内存临界于前项) 修改前项的参数;移动链表起始指针; 记录成功; 跳出; else if(要求释放的内存临界于后项) 修改后项的参数;移动链表起始指针; 记录成功; 跳出; else if(前后项地址相同) /*只有一项*/ 同样按以上三种情况处理; else if(释放区域在两项之中,且临界) 合并、修改前后项,并删除前项;移动链表起始指针; 记录成功; 跳出; else if(释放区域与前项临界) 修改前项;移动链表起始指针; 记录成功; 跳出; else if(释放区域与后项临界) 修改后项;移动链表起始指针;记录成功; 跳出; else if(释放区域在前后项之中,不临界) 申
11、请新表项;初始化并完善链表;记录成功;跳出; while(起始指针不等于遍历指针) if(没有记录成功) x_ErrorApply( );七、 原程序代码请参见F005-093-LiuXin.c ,其中包含有测试数据及测试结果八、 测试方案及结果在本实验中,我们采用白盒法的方法,即保证每一条支路都要至少走一遍。因此,根据这个方法,我设计了如下的测试用例,并得到了如后所述的测试结果。1 输入的命令不符合格式:lmallod 200 lmalloc 23j3lfres 200 200lfree 200lfree 3j2 200lfree 200 3j3ent理论输出均应为:Your input i
12、s invalid, please input in standard way. That is, lmalloc(lfree) size(address) (free size) or end.实际结果正确。2 一次分配内存完毕,空闲内存分区表无剩余,再次要求分配内存,显示无内存信息。lmalloc 1024lmalloc 20理论输出应为: Allocating Succeed! The Given Address is 0 Not enough memory, please free or apply for less memory!实际结果正确。3释放内存(此时空闲表无节点,新建节点)
13、lfree 200 100lfree 100 100 (单节点,与后空间临界)lmalloc 100 lfree 300 100 (单节点,与前空间临界)lmalloc 100lfree 50 50 (单节点,与该空间无关)lmalloc 50 lfree 200 50 (单节点,与该空间无关)lmalloc 50 lmalloc 100lfree 200 100lfree 400 100lfree 600 100lfree 800 100lfree 500 100 (连接前后两个节点)lfree 700 50 (连接前面的空间)lfree 751 49 (连接后面的空间)lfree 320
14、50 (与前后空间均无临界)lfree 100 100 (前后交界处,和前空间临界)lfree 900 100 (前后交界处,和后空间临界)lfree 1001 20 (前后交界处,与前后空间均无临界)lfree 40 40 (前后交界处,与前后空间均无临界)lfree 1025 20 (越界)lfree 100 1000 (越界)lfree 450 500 (和已空闲区域相冲突)经测试结果均正确4申请内存(多个内存空闲区域情况下)lmalloc 40 (需要删除节点)lmalloc 300 (不删除节点)经测试结果均正确5终止程序 在测试过程中,已经测试过了单节点情况下的退出,情况正常。 现
15、在的测试文件中的退出为多节点情况下的退出,情况也正常。经上述白盒法测试,暂时没有发现程序存在问题。九、 实验体会1 本实验中的程序虽然不大,但还是有几个地方比较麻烦。首先是命令的录入及识别问题。采用scanf函数不仅有处理空格、回车之类键入的麻烦,而且我觉得也难以对命令输入的格式做出比较好的要求。因此我采用了gets()函数,使用该函数的确不存在对于空格、回车之类输入的错误反应的问题。但随之而来的麻烦是,如何将较好地字符型整数转化为整数型。这一工作并没有什么难度,但比较繁琐。经过我的处理之后的输入系统,基本上可以做到仅仅识别1种标准格式的输入,不在输入阶段产生问题。2 系统的友好度的问题。虽然
16、说本程序的用途仅仅是仿真模拟unix内存分配,因此实际上考虑与用户之间交互的用好度并没有什么意义。所以我一开始采用了分配内存实际物理地址返回,实际物理地址输入方能释放内存的方法,但显然这样非常的别扭,而且难以看懂。于是后来我改用了物理的相对地址。即以分配所得的内存首址作为相对地址0,以后的地址相应推的。经过这样的改变以后,不仅对于测试来说变得简单明了,而且确实增加了系统交互的友好度。我想如果设计的程序是和用户交互的话,那么这个方面要注意。3 分类的重要性。本程序另一大难点在于lfree函数中具体情况的处理。因为释放的情况比较复杂,处理的方式也不太一样,而且还要兼顾到空闲区域表中的单元数量情况,
17、因此比较麻烦。我最初的程序设计中,分类并不够细致,没有将这个问题细化,所以曾经变成效率较低。后来我重新对这一部分作了分析,划分了较多的情况,虽然比较繁琐,但应当说,程序变得明了清晰。程序:/*This program is to simulate the memory allocating in Unix using the First to fit algorithm. There are 9 sub-functions in this program. x_Initialize()-to initialize the memory space and the table used to r
18、ecord the condition of memory allocating. x_Order()-to deal with the orders gived by user. x_ErrorOrder()-to deal with the error taking place in function x_Order(). x_ApplyMem()-to apply for the memory space. x_ErrorApply()-to deal with the error taking place in function x_ApplyMem(). x_FreeMem()-to
19、 free the memory space given by user. x_ErrorFree()-to deal with the error taking place in function x_ErrorFree(). x_PrintTable()-to output the free memory condition table to terminals. x_EndProgram()-to end the program and free all the memory space occupied. This program is developed on 15th,Sep by
20、 Xin,Liu F005 Shanghai JiaoTong Uni. F005 5004129093 Liu Xin*/#include stdio.h#include math.h#include stdlib.h#include string.h/*This part is to define the data stucture and variables used in the program.*/struct map/*unit in the free space record table*/ unsigned long x_MemSize; char *x_MemAddr; st
21、ruct map *x_TablePrev,*x_TableNext;struct map *x_TableStart; /* Pointer of the free space table */unsigned long x_WholeMemSize=1024; /* The size of available memory */char *x_Start; /* The beginning address of the free space */void main() /*This part is to declare the sub-functions in the program.*/
22、 void x_Initialize(); void x_Order(); void x_ErrorOrder(); char *x_ApplyMem(unsigned long x_MemAmount); void x_ErrorApply(); void x_MemFree(unsigned long x_FreeAddr,unsigned long x_MemAmount); void x_ErrorFree(); void x_PrintTable(); void x_EndProgram(); /*This part is to apply for the memory space.
23、*/ x_Start=(char *)malloc(x_WholeMemSize); /*This part is to finish the task of the problem.*/ x_Initialize(x_Start,x_WholeMemSize,x_TableStart); x_Order(x_Start,x_TableStart);void x_Initialize()/* To initialize the free space table */ char out50=The initialization work has been finished! n; x_Table
24、Start=(struct map *)malloc(sizeof(struct map); 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();void x_Order() char x_UserOrder30; /* to save users order */ int x_MallocIdt=0
25、; int x_FreeIdt=0; int x_EndIdt=0; /* above 3 to identify users order */ int i=0; /* to record the times */ char x_Malloc8=lmalloc ; char x_Free6=lfree ; char x_End4=end0; for(;) /*To get the input of a user a */ printf(Command:); gets(x_UserOrder); x_MallocIdt=0; x_FreeIdt=0; x_EndIdt=0; /*To ident
26、ify the order*/ for(i=0;i=7;i+) /* identify malloc a */ if(x_Malloci=x_UserOrderi) x_MallocIdt+; for(i=0;i=5;i+) /* identify free a */ if(x_Freei=x_UserOrderi) x_FreeIdt+; for(i=0;i=0)&(x_UserOrderi=0)&(x_UserOrderi=9);) /* To save the physical relative address ) a */ x_FreeAddr=x_FreeAddr*10+(x_UserOrderi-0); i+; if(x_UserOrderi!= ) /* invalid input a */ x_ErrorOrder(); else /* address is OK a */
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1