物联网工程 201306104124 施振成
一、 实验目的
为了合理地分配和使用这些存储空间,当用户提出申请主存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间和使用情况,找出足够 的空闲区域给申请者。当作业撤离归还主存资源时,则存储管理要收回占用的主存空间。主存的分配和回收的实现是与主存储器的管理方式有关的,通过本实验帮助 我们理解在不同的存储管理方式下应怎样实现主存空间的分配和回收。
用高级语言完成一个主存空间的分配和回收模拟程序,以加深对内存分配方式及其算法的理解。
二、实验内容和要求
2.1 模拟包括3部分:
1)实现特定的内存分配算法
2)实现内存回收模拟
3)每种内存分配策略对应的碎片数统计
2.2 固定分区存储管理
假设内存容量为120KB,并且分别划分成8,16,32,64KB大小的块各一块。
一个进程所需要的内存为0到100个KB。同时假设一个进程在运行过程中所需内存的大小不变。
模拟五个进程到达请求分配与运行完回收情况,输出主存分配表.
2.3 动态分区分配存储管理
采用连续分配方式之动态分区分配存储管理,使用首次适应算法、下次适应算法、最佳适应算法和最坏适应算法4种算法完成设计(任选两种算法)。
(1)在程序运行过程,由用户指定申请与释放。
(2)设计一个已占用分区表,以保存某时刻主存空间占用情况。
(3)设计一个空闲分区表,以保存某时刻主存空间剩余情况。
(4)用两个表的变化情况,反应各进程所需内存的申请与释放情况。
三、实验方法、步骤及结果测试
主要程序段及其解释:
#include<stdio.h> #include<malloc.h> struct FBT { int startdress;//分区首地址 int size;//分区所占内存大小 int processid;//申请内存分区的进程号 int state;//分区状态 struct FBT *next; }; struct FBT *create() //*块表 { struct FBT *head,*p,*q; head=NULL; p=(struct FBT *)malloc (sizeof(struct FBT)); q=(struct FBT *)malloc (sizeof(struct FBT)); head=p; p->size=5;//系统分区,大小为5 p->processid=-1;//-1表示操作系统的固定分区 p->startdress=0;//开始地址为0 p->state=1;//状态为已分配,置1 p->next=q; q->size=115;//余下分区大小 q->processid=0;//进程号为0,表示未分配 q->startdress=5;//起始地址为5 q->state=0; q->next=NULL; return head; } struct FBT *distribute(struct FBT*head)//分配内存子函数 { int id,needsize; struct FBT *pretail,*tail,*p; printf("输入要申请内存的进程号:");//输入申请内存的进程号 scanf("%d",&id); printf("请输入申请的内存大小:");//输入申请的内存大小 scanf("%d",&needsize); pretail=tail=head; while(tail!=NULL) { if(tail->state==0&&tail->size>=needsize)//如果此分区没有分配,而且大小大于等于申请的内存大小 { if(tail->size>needsize)//如果此分区大小大于要申请的大小,分配,并把余下的再分割成一个分区 { p=(struct FBT *)malloc (sizeof(struct FBT)); p->size=needsize; p->processid=id; p->startdress=tail->startdress; p->state=1; if(head!=tail) { pretail->next=p; p->next=tail; pretail=p; } else { p->next=tail; head=p; tail->next=NULL; } tail->startdress=p->startdress+p->size; tail->size=tail->size-needsize; break; } if(tail->size==needsize)//如果此分区等于要申请的大小,直接分配即可 { tail->processid=id; tail->state=1; break; } } else //否则,指向下一个结点继续判断 { pretail=tail; tail=tail->next; } } if(tail==NULL)//如果遍历完链表都没有找到合适的分区分配,则显示以下信息 printf("\n没有足够的空间!\n"); return head; } struct FBT *callback(struct FBT *head)//回收内存子函数 { int id; struct FBT *pretail,*tail; printf("请输入进程号:"); scanf("%d",&id); pretail=tail=head; while(tail!=NULL)//遍历链表 { if(tail->processid==id)//如果改分区所对应的进程号要收回分区的进程号,则做以下动作 { if(tail->next!=NULL)//如果改分区不是最后一个分区,则作以下动作 { if(pretail->state==1&&tail->next->state==1)//前一个分区是已分配的且后一个分区也是已分配的 { tail->state=0; break; } if(pretail->state==0&&tail->next->state==1)//前一个分区是未分配的且后一个分区也是已分配的 { pretail->next=tail->next; pretail->size=tail->size+pretail->size; free(tail); break; } if(pretail->state==1&&tail->next->state==0)//前一个分区是已分配的且后一个分区是未分配的 { if(pretail!=tail) { pretail->next=tail->next; tail->next->size=tail->next->size+tail->size; tail->next->startdress=tail->startdress; free(tail); break; } else { head=tail->next; tail->next->startdress=0; tail->next->size+=tail->size; break; } } if(pretail->state==0&&tail->next->state==0)//前一个分区和后一个分区都未分配的 { pretail->next=tail->next->next; pretail->size=pretail->size+tail->size+tail->next->size; free(tail->next); free(tail); break; } } else//如果该分区是最后一个分区则作以下动作 { if(pretail->state==1)//如果前一个分区是已分配的 { tail->state=0; break; } else//如果前一个分区是未分配的 { pretail->next=NULL; pretail->size=pretail->size+tail->size; free(tail); break; } } } pretail=tail; tail=tail->next;//遍历下一个分区结点 } return head;//返回头指针 } void print(struct FBT *head)//显示FBT的内容给客户 { struct FBT *tail=head; printf("startdress\tsize\tstate\t\tprocessid\t\n"); tail=head; while(tail!=NULL) { if(tail->state==1) printf("%5d\t\t%5d\t%5d\t\t%5d\n",tail->startdress,tail->size,tail->state,tail->processid); else printf("%5d\t\t%5d\t%5d\n",tail->startdress,tail->size,tail->state); tail=tail->next; } } void main()//主函数 { int choice=1; struct FBT *head; head=create(); while(choice!=0) { printf("\t1.申请内存\n"); printf("\t2.回收内存\n"); printf("\t3.退出\n"); printf("请选择:"); scanf("%d",&choice); switch(choice) { case 1: head=distribute(head); print(head); break; case 2: head=callback(head); print(head); break; case 0:break; default: printf("输入错误!\n"); } } }
运行结果:
四、总结
这次内存分配的实验做得有点简单,很多都是借鉴同学和网上的,只是初步看懂了大部分代码 ,总结整个的流程。以后会对本次实验进行复习加深印象。