操作系统原理内存分配与回收.docx
- 文档编号:26479757
- 上传时间:2023-06-19
- 格式:DOCX
- 页数:17
- 大小:170.06KB
操作系统原理内存分配与回收.docx
《操作系统原理内存分配与回收.docx》由会员分享,可在线阅读,更多相关《操作系统原理内存分配与回收.docx(17页珍藏版)》请在冰豆网上搜索。
操作系统原理内存分配与回收
内存的动态存储管理
一、实验内容
编写程序实现动态分区存储管理方式的主存分配与回收。
具体内容包括:
首先确定主存空间分配表;然后采用最先适应算法完成主存空间的分配与回收;最后编写主函数对所做工作进行测试
二、实验原理
模拟存储管理中内存空间的管理和分配内存空间的管理分为固定分区管理方式,可变分区管理方式,页式存储管理,段式存储管理。
题目:
模拟内存分配与回收
三、实验步骤(或过程)
在Microsoft Visual C++ 6.0环境下运行
1.设计一个空闲分区表,空闲分区表通过空闲分区链表来管理,在进行内存分配时,系统优先使用空闲分区低端的空间。
2.设计一个内存分区表,可用链表管理,用以表示当前以内存使用情况。
3.设计一个进程申请队列以及进程完成后的释放顺序,实现主存的分配和回收。
4.要求每次分配和回收后把空闲分区的变化情况以及各进程的申请、释放情况以及各进程的申请、释放情况以图形方式显示、打印出来。
最佳适应算法:
该算法总是把满足要求、又是最小的空闲区分配给作业。
检查空闲区说明表是否有满足作业要求的空闲区,也分为三种情况:
大于,等于,小于。
若检查到有“等于”的情况,就可以直接分配,若没有,则继续检查是否有“大于”的情况
代码实现如下:
#include
#include
#include
#definen64//定义内存的大小
inta[n],count=0;//数组a用来保存内存使用状况1为已分配0为未分配,count用来记name数组中元素个数
charname[n];//已分配内存的名称(字符类型)
typedefstructlinknode{
charpid;
intstart;
intlength;
structlinknode*left,*right;
}de_node;//进程节点结构体定义
//head1表示未分配内存队列头指针,head2便是已分配进程队列头指针
de_node*head1,*head2=NULL;
structlinknode*creat()//创建一个进程节点
{
intlen,flag1=1;//用于表示进程是否可以创建
charid;
structlinknode*p;
p=(de_node*)malloc(sizeof(de_node));//试图在系统内存中开辟空间创建一个进程
if(p==NULL)//p为空,说明系统没有可用内存用于创建此模拟进程
{printf("系统没有足够的内存可供使用!
\n");//输出
return(NULL);//返回空指针
}
printf("请输入进程id(字符类型)和长度:
");//为进程输入id和分配的长度
scanf("%c%d",&id,&len);
fflush(stdin);//清除输入缓存
if((id>='a'&&id<='z'||id>='A'&&id<='Z')&&(len>0)){
for(inti=0;i if(name[i]==id){ printf("此名称进程已存在! ! "); flag1=0;//标志位为0,表示下面对p指向内容不做修改 free(p); returnNULL; } if(len==0){//如果输入要分配的进程长度为0,释放p,返回空指针 printf("输入长度为0! \n"); free(p); return(NULL); } if(flag1){//标志位1,可以对p指向内容进行修改 p->pid=id;//id p->start=0;//初始开始内存位置,在以后会修改 p->length=len;//长度 p->left=NULL;//左指针 p->right=NULL;//右指针 name[count++]=id;//将id存入数组,count自加 return(p); }//返回创建的进程的地址 } else{printf("输入进程格式有误\n"); free(p); return(NULL); } } //分配内存空间 voiddistribute(de_node*p) {de_node*q=head1,*temp; intflag=0; do{//do_while循法 //判断当前指向的内存空间的长度是否满足p所申请的长度,大于就分配 if(q->length>=p->length){ p->start=q->start;//把进程的内存开始地址指向内存的可用开始地址处 q->start+=p->length;//可用地址起始改变 q->length-=p->length;//可用内存长度修改 for(inti=p->start;i a[i]=1; flag=1;//表示内存可分配 //队列不止一个进程,第一个满足条件,并且刚好分配完,修改指针指向 if(q->length==0&&q->right! =q) {if(q==head1)//如果第一个满足,修改头指针指向 head1=q->right; q->left->right=q->right; q->right->left=q->left; free(q);//把这个已分配完的空间指针释放 } } if(flag==1)//已做完处理直接跳出循环 break; if(flag==0)//当前指向的内存不满足,指向下一个,继续判断是否满足 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;//双向队列第一个左右指针都指向自己 p->right=p;//双向队列第一个左右指针都指向自己 } elseif(temp! =NULL){//已存在队列,把当前直接链到第一个,与上面的区别是指针指向 head2=p;//让头指针指向p指向的进程 p->left=temp->left;//p进程左边为原来第一个的左边 p->right=temp;//p进程右边指向第一个 temp->left->right=p;//原来第一个的左边为p temp->left=p;//原来第一个的左边的进程为p } } } //对进程的回收 voidreclaim() {charid; intflag=0; de_node*q=head2,*p=head1; if(head2==NULL)//表示当前没有进程 {printf("已没有进程! \n"); } else{//已分配内存队列如果不为空 printf("输入要回收的进程id: ");//输入要回收进程的id scanf("%c",&id); fflush(stdin); for(inti=0;i if(name[i]==id) {//判断当前的进程是否满足要求 for(intj=i;j name[j]=name[j+1];//向前覆盖 name[j+1]=NULL;//置空 count--;//减一 } //判断是否总共只有一个进程且是够刚好也满足条件if(q->pid==id&&q->right==q&&head2==q) {head2=NULL;//把已分配队列直接置空 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; } elseq=q->right; }while(q! =head2); }//如果找到或是遍历一遍结束 if(flag==0)printf("没有此进程号! ! ! \n");//没有找到满足的进程 if(flag==1){//表示找到了 for(inti=q->start;i a[i]=0; //接下来修改可用内存的队列, while(q->start>p->start&&p->right! =head1){ //从第一个开始找到回收回来的内存开始地址大的那个队列p=p->right; } if(p==head1)//表示比第一个的开始还小,那么就要修改头地址 head1=q;//其他情况不用修改头地址,只需找到应该的位置,把此进程插进去 q->left=p->left;//修改指针的指向 q->right=p; p->left->right=q; p->left=q;if(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); } } } } //打印输出 voidprint() {de_node*q=head2,*p=head1; if(count==0) printf("没有进程占有内存。 \n"); else {printf("输出进程id号: \n"); for(inti=0;i printf("%c\t",name[i]); } printf("\n"); printf("输出内存当前使用情况: \n"); for(intj=0;j printf("%d%d\t",j,a[j]); printf("\n"); printf("内存初始名称为i,回收后可能会变,可以查看回收来自那个进程\n"); do//输出可用内存序列 {if(p! =NULL) {printf("进程id: %c开始地址: %d长度%d\n",p->pid,p->start,p->length); p=p->right; } }while(p! =head1); printf("\n"); printf("已分配进程队列: \n"); do//已分配进程队列 { if(q! =NULL) { printf("进程id: %c开始地址: %d长度%d\n",q->pid,q->start,q->length); q=q->right; } }while(q! =head2); } //主函数 voidmain() {intx; de_node*point,*p1; //创建内存的初始状态 point=(structlinknode*)malloc(sizeof(structlinknode)); 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("%d",&x); fflush(stdin); switch(x) { case1: {p1=creat(); if(p1==NULL)printf("创建进程失败。 \n"); elsedistribute(p1); x=0; break; } case2: {reclaim(); x=0; break; } case3: {print(); x=0; break;} case4: {printf("Thanks;Bye-bye! ");exit(0); x=0; break;} default: {printf("输入有误,请重新输入。 \n");} } } } 四、实验结论 1、实验结果 2、分析讨论 在作业存储时,当前作业的起始地址=原空闲区起始地址+原空闲区偏移地址-当前作业的偏移地址;由此可知当前作业在空闲区内是从空闲区的高地址开始分配。 通过这次课程设计,我把学到的操作系统的知识和VC程序的设计灵活的结合到一起。 虽然在设计过程中也遇到了不少问题,但最后都能得到解决而在这种过程中也使我加深了内存分配概念的理解和掌握基本内存分配的方法。 相信在今后我会把我学到的各种知识运用的更好。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 原理 内存 分配 回收