实验四 主存空间的分配和回收模拟
13物联网工程 李小娜 201306104148
一、实验目的
为了合理地分配和使用这些存储空间,当用户提出申请主存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间和使用情况,找出足够的空闲区域给申请者。当作业撤离归还主存资源时,则存储管理要收回占用的主存空间。主存的分配和回收的实现是与主存储器的管理方式有关的,通过本实验帮助我们理解在不同的存储管理方式下应怎样实现主存空间的分配和回收。
用高级语言完成一个主存空间的分配和回收模拟程序,以加深对内存分配方式及其算法的理解。
二、实验内容和要求
2.1 模拟包括3部分:
1) 实现特定的内存分配算法
2) 实现内存回收模拟
3) 每种内存分配策略对应的碎片数统计
2.2 固定分区存储管理:
假设内存容量为120KB,并且分别划分成23,24,25,26KB大小的块各一块。
一个进程所需要的内存为0到100个KB。同时假设一个进程在运行过程中所需内存的大小不变。
模拟五个进程到达请求分配与运行完回收情况,输出主存分配表.
2.3 动态分区分配存储管理
采用连续分配方式之动态分区分配存储管理,使用首次适应算法、下次适应算法、最佳适应算法和最坏适应算法4种算法完成设计(任选两种算法)。
(1)在程序运行过程,由用户指定申请与释放。
(2)设计一个已占用分区表,以保存某时刻主存空间占用情况。
(3)设计一个空闲分区表,以保存某时刻主存空间剩余情况。
(4)用两个表的变化情况,反应各进程所需内存的申请与释放情况。
三、实验方法、步骤及结果测试
- 程序段及其解释:
1.1固定分区
代码:
#include <stdio.h> #include <stdlib.h> typedef struct linknode { int number;//分区号 int size;//大小 int start;//起始地址 char state;//,0表示未分配 }node; main() { node a[10]; int i,j,n,k,flag=1,FLAG; char t; a[1].number=1; a[1].size=8; a[1].start=8; a[1].state='0'; a[2].number=2; a[2].size=16; a[2].start=16; a[2].state='0'; a[3].number=3; a[3].size=32; a[3].start=32; a[3].state='0'; a[4].number=4; a[4].size=64; a[4].start=64; a[4].state='0'; printf("各分区分配情况是: "); printf("分区号 大小 起址 状态 "); for(i=1;i<=4;i++) { printf("%d %d %d %c ",a[i].number,a[i].size,a[i].start,a[i].state); } while(flag) { flag=0; FLAG=0; printf("请输入作业名称(用字符表示)和作业大小: "); scanf("%c%d",&t,&k); for(i=1;i<=4;i++) { if(a[i].state=='0'&&k<=a[i].size) { a[i].state=t; FLAG=1;break; } } if(FLAG==0) goto L; printf("分配后: "); printf("分区号 大小 起址 状态 "); for(i=1;i<=4;i++) { printf("%d %d %d %c ",a[i].number,a[i].size,a[i].start,a[i].state); if(a[i].state=='0') flag=1; } getchar(); } L:printf("存储区已满或没有足够大的分区给此作业分配空间 "); }
1.2 动态分区
代码:
#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; //状态为未分配,置0 q->next=NULL; //指向下一个分区,因为只有两个分区,所以为空 return head; } struct FBT *distribute(struct FBT*head) //分配内存子函数 { int id,needsize; struct FBT *pretail,*tail,*p; printf("输入要申请内存的进程号:"); scanf("%d",&id); if(id==-1) { printf("进程号为-1代表操作系统进程,请重输:"); 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(" 没有足够的空间!! "); return head; //返回头指针 } struct FBT *callback(struct FBT *head)//回收内存子函数 { int id; struct FBT *pretail,*tail; printf("请输入进程号:"); scanf("%d",&id); if(id==-1) { printf("进程号为-1代表操作系统进程,请重输:"); 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 size state processid "); tail=head; while(tail!=NULL) { if(tail->state==1) printf("%5d %5d %5d %5d ",tail->startdress,tail->size,tail->state,tail->processid); else printf("%5d %5d %5d ",tail->startdress,tail->size,tail->state); tail=tail->next; } } void main() { int choice; struct FBT *head; head=create(); while(1) { printf(" 1.申请内存 "); printf(" 2.回收内存 "); printf(" 3.退出 "); printf("请选择:"); scanf("%d",&choice); switch(choice) { case 1: head=distribute(head); print(head); break; case 2: head=callback(head); print(head); break; case 3: exit(0); default: printf("输入错误!请重输! "); } } }
- 运行结果
固定分区结果图
初始内存分区情况
插入进程1后的分区情况
插入进程2后的分区情况
插入进程3后的分区情况
插入进程4后的分区情况,此时内存空间已满
动态分区结果图
若申请进程号为-1则提示为系统进程,要求再输入
正常申请进程情况
若申请的内存大于剩余空间则给予用户提示并显示目前内存使用情况
正常回收内存情况
若输入回收进程号为-1则提示为系统进程并要求用户重输
退出情况
四、实验总结
这次实验写的比较赶也比较难,尤其是动态分区模块。所以最后在网上搜了资源程序,但发现代码有些错误,修改完善并理解后就匆忙结束了。只能说这次就是在理解别人的代码吧,但还是有收获的。