1、内存的动态存储管理一、实验内容编写程序实现动态分区存储管理方式的主存分配与回收。具体内容包括:首先确定主存空间分配表;然后采用最先适应算法完成主存空间的分配与回收;最后编写主函数对所做工作进行测试二、实验原理模拟存储管理中内存空间的管理和分配内存空间的管理分为固定分区管理方式,可变分区管理方式,页式存储管理,段式存储管理。题目:模拟内存分配与回收三、实验步骤(或过程)在 Microsoft Visual C+ 6.0 环境下运行1设计一个空闲分区表,空闲分区表通过空闲分区链表来管理,在进行内存分配时,系统优先使用空闲分区低端的空间。 2设计一个内存分区表,可用链表管理,用以表示当前以内存使用情
2、况。 3设计一个进程申请队列以及进程完成后的释放顺序,实现主存的分配和回收。 4要求每次分配和回收后把空闲分区的变化情况以及各进程的申请、释放情况以及各进程的申请、释放情况以图形方式显示、打印出来。最佳适应算法:该算法总是把满足要求、又是最小的空闲区分配给作业。检查空闲区说明表是否有满足作业要求的空闲区,也分为三种情况:大于,等于,小于。若检查到有“等于”的情况,就可以直接分配,若没有,则继续检查是否有“大于”的情况代码实现如下:#include #include #include #define n 64 /定义内存的大小int an,count=0;/数组 a 用来保存内存使用状况 1 为
3、已分配 0 为未分配,count 用来记 name数组中元素个数char namen;/已分配内存的名称(字符类型)typedef struct linknodechar pid;int start;int length;struct linknode *left,*right;de_node; /进程节点结构体定义/head1 表示未分配内存队列头指针,head2 便是已分配进程队列头指针de_node *head1,*head2=NULL;struct linknode* creat()/创建一个进程节点int len,flag1=1;/用于表示进程是否可以创建char id;struct
4、 linknode* p;p = (de_node *)malloc(sizeof(de_node);/试图在系统内存中开辟空间创建一个进程if (p=NULL) /p 为空,说明系统没有可用内存用于创建此模拟进程 printf(“系统没有足够的内存可供使用!n“);/ 输出return(NULL);/返回空指针printf(“请输入进程 id(字符类型)和长度:“);/ 为进程输入 id 和分配的长度scanf(“%c %d“,fflush(stdin);/清除输入缓存if(id=aipid=id; /id p-start=0; /初始开始内存位置,在以后会修改p-length=len;/长
5、度p-left=NULL;/左指针p-right=NULL;/右指针namecount+=id;/将 id 存入数组,count 自加return(p);/返回创建的进程的地址else printf(“输入进程格式有误n“);free(p);return (NULL);/分配内存空间void distribute(de_node *p) de_node *q=head1,*temp;int flag=0;do/do_while 循法/判断当前指向的内存空间的长度是否满足 p 所申请的长度 ,大于就分配if(q-length=p-length) p-start=q-start;/把进程的内存开始
6、地址指向内存的可用开始地址处q-start+=p-length;/可用地址起始改变q-length-=p-length;/可用内存长度修改for(int i=p-start;istart+p-length;i+)/将已分配的内存空间全部置 1ai=1;flag=1;/表示内存可分配/队列不止一个进程,第一个满足条件,并且刚好分配完,修改指针指向if(q-length=0q-left-right=q-right;q-right-left=q-left;free(q);/把这个已分配完的空间指针释放if(flag=1)/已做完处理直接跳出循环break;if(flag=0)/当前指向的内存不满足,
7、指向下一个,继续判断是否满足q=q-right;while(q!=head1);/搜索一遍可用内存序列if(flag=0)/没有可用的内存printf(“没有满足的内存!n“);count-;/由于创建时加 1,但在分配内存时失败,把 1 又减掉free(p);/把这个未分配到内存的进程释放if(flag=1)/表示上面已分配好内存,并已修改内存链表,下面修改已分配内存的进程队列temp=head2;/把已分配内存的进程队列赋值给临时指针if(temp=NULL)/如果还还没有存在的任何的进程,说明当前是第一个 head2=p;/让头指针指向第一个进程p-left=p;/双向队列第一个左右指针
8、都指向自己p-right=p;/双向队列第一个左右指针都指向自己else if(temp!=NULL)/已存在队列,把当前直接链到第一个,与上面的区别是指针指向head2=p;/让头指针指向 p 指向的进程p-left=temp-left;/p 进程左边为原来第一个的左边p-right=temp;/p 进程右边指向第一个temp-left-right=p;/原来第一个的左边为 ptemp-left=p;/原来第一个的左边的进程为 p/对进程的回收void reclaim() char id;int flag=0;de_node *q=head2,*p=head1;if(head2=NULL)/
9、表示当前没有进程 printf(“已没有进程!n“);else /已分配内存队列如果不为空printf(“输入要回收的进程 id: “);/输入要回收进程的 idscanf(“%c“,fflush(stdin);for(int i=0;ipid=id/把已分配队列直接置空flag=1;/表示找到满足条件的进程if(flag=0)/上面的都没找到do if(q-pid=id)/如果找到 if(q=head2) head2=q-right; q-left-right=q-right;/修改指针指向 q-right-left=q-left;flag=1;break;else q=q-right;wh
10、ile(q!=head2); /如果找到或是遍历一遍结束 if(flag=0) printf(“没有此进程号! n“);/没有找到满足的进程if(flag=1)/表示找到了for(int i=q-start;istart+q-length;i+)/释放占有的内存ai=0;/接下来修改可用内存的队列,while(q-startp-startif(p=head1)/表示比第一个的开始还小,那么就要修改头地址head1=q;/其他情况不用修改头地址,只需找到应该的位置,把此进程插进去q-left=p-left;/修改指针的指向q-right=p;p-left-right=q;p-left=q; if
11、(q-start+q-length=p-start)/可以与后面合并的情况 q-length+=p-length;/修改指针的指向 p-right-left=q; q-right=p-right;free(p); if(q-left-start+q-left-length=q-start)/可以与前面合并的情况 q-left-length+=q-length;/修改指针的指向 q-left-right=q-right; q-right-left=q-left;free(q); /打印输出void print() de_node *q=head2,*p=head1;if(count=0)prin
12、tf(“没有进程占有内存。n“);else printf(“输出进程 id 号:n“);for(int i=0;ipid,p-start,p-length);p=p-right;while(p!=head1);printf(“n“);printf(“已分配进程队列:n“);do /已分配进程队列if(q!=NULL)printf(“进程 id:%c 开始地址:%d 长度%dn“,q-pid,q-start,q-length);q=q-right;while(q!=head2);/主函数void main() int x;de_node *point,*p1;/创建内存的初始状态point=(s
13、truct linknode*)malloc(sizeof(struct linknode);head1=point;point-pid=i;point-start=0;point-length=n;head1-left=point;head1-right=point;print();while(1)printf(“ -MENU-n“);printf(“1-distribute(分配)n“);printf(“2-reclaim(回收)n“);printf(“3-view (浏览)n“);printf(“4-exit(退出)n“);printf(“请输入上面的选项(1-4):n“);scanf(
14、“%d“,fflush(stdin);switch(x)case 1: p1=creat();if(p1=NULL) printf(“创建进程失败。n“);else distribute(p1);x=0;break;case 2: reclaim();x=0;break;case 3: print();x=0;break;case 4: printf(“Thanks;Bye-bye!“);exit(0);x=0;break;default: printf(“输入有误,请重新输入。n“);四、实验结论1、实验结果2、分析讨论在作业存储时,当前作业的起始地址=原空闲区起始地址+原空闲区偏移地址-当前作业的偏移地址;由此可知当前作业在空闲区内是从空闲区的高地址开始分配。通过这次课程设计,我把学到的操作系统的知识和 VC 程序的设计灵活的结合到一起。虽然在设计过程中也遇到了不少问题,但最后都能得到解决而在这种过程中也使我加深了内存分配概念的理解和掌握基本内存分配的方法。相信在今后我会把我学到的各种知识运用的更好。