操作系统第5次实验报告:内存管理
- 姓名:祁翌炀
- 学号:201821121019
- 班级:计算1811
1. 记录内存空间使用情况
首先建立一个进程链表,对每个进程进行空间的分配,创建新进程,在创建进程的时候进行分配空间和pid
int create_process() { struct allocated_block *ab; int size;//大小 int ret; ab= (struct allocated_block*)malloc(sizeof(struct allocated_block)); if(!ab) exit(-5); ab->next= NULL; pid++; sprintf(ab->process_name,"进程-%02d",pid);//此处为进程的pid号,pid号为从0开始 ab->pid= pid; for(;;) { size=rand()%51+50;//此处为随机分配内存,50-100 printf("Memory for %s is %d\n",ab->process_name,size); if(size> 0) { ab->size= size; break; } else printf("The size have to greater than zero!Please input again!"); } ret= allocate_mem(ab); if((ret== 1)&&(allocated_block_head== NULL)) //如果此时未赋值,则赋值 { allocated_block_head= ab; return 1; } else if(ret== 1) //分配成功,将该已分配块的描述插入已分配链表 { ab->next= allocated_block_head; allocated_block_head= ab; return 2; } else if(ret== -1) //分配不成功 { printf("Allocation fail.\n"); free(ab); return -1; } return 3; }
此处为展示函数,展示内存空间使用情况
int showmemuse() { struct free_block_type *fbt= free_block; struct allocated_block *ab= allocated_block_head; printf("-------------------------------------------------------------\n"); printf("Use Memory:\n"); printf("%10s %20s %10s %10s\n","PID","ProcessName","start_addr","size"); while(ab!= NULL) { printf("%10d %20s %10d %10d\n",ab->pid,ab->process_name,ab->start_addr,ab->size); ab= ab->next; } printf("-------------------------------------------------------------\n"); printf("Free Memory:\n"); printf("%20s %20s\n"," start_addr"," size"); while(fbt!= NULL) { printf("%20d %20d\n",fbt->start_addr,fbt->size); fbt= fbt->next; } printf("\n"); return 1; }
2. 记录空闲分区
首先定义空闲区块的结构体,大小,位置,next指针
struct free_block_type { int size; //空闲块大小 int start_addr; //空闲块起始位置 struct free_block_type *next; //指向下一个空闲块 }; //指向内存中空闲块链表的首地址 struct free_block_type *free_block= NULL;
//按FF算法重新整理内存空闲块链表,按空闲块首地址排序 int rearrange_FF() { struct free_block_type *head= free_block; struct free_block_type *forehand,*pre,*rear; int i; if(head== NULL) return -1; for(i= 0;i< free_block_count-1;i++) { forehand= head; pre= forehand->next; rear= pre->next; while(pre->next!= NULL) { if(forehand== head&&forehand->start_addr>= pre->start_addr) { //比较空闲链表中第一个空闲块与第二个空闲块的开始地址的大小 head->next= pre->next; pre->next= head; head= pre; forehand= head->next; pre= forehand->next; rear= pre->next; } else if(pre->start_addr>= rear->start_addr) { //比较链表中其它相邻两个结点的开始地址的大小 pre->next= rear->next; forehand->next= rear; rear->next= pre; forehand= rear; rear= pre->next; } else { forehand= pre; pre= rear; rear= rear->next; } } } return 0; }
同理可得BF与WF的算法与FF不同,但是结构相似,不同处在于比较的地方不同
//按BF算法重新整理内存空闲块链表,按空闲块大小从小到大排序 int rearrange_BF() { struct free_block_type *head= free_block; struct free_block_type *forehand,*pre,*rear; int i; if(head== NULL) return -1; for(i= 0;i< free_block_count-1;i++) { forehand= head; pre= forehand->next; rear= pre->next; while(pre->next!= NULL) { if(forehand== head&&forehand->size<= pre->size) { //比较空闲链表中第一个空闲块与第二个空闲块的空间的大小 head->next= pre->next; pre->next= head; head= pre; forehand= head->next; pre= forehand->next; rear= pre->next; } else if(pre->size<= rear->size) { //比较链表中其它相邻两个结点的空间的大小 pre->next= rear->next; forehand->next= rear; rear->next= pre; forehand= rear; rear= pre->next; } else { forehand= pre; pre= rear; rear= rear->next; } } } return 0; } //按WF算法重新整理内存空闲块链表,按空闲块大小从大到小排序 int rearrange_WF() { struct free_block_type *head= free_block; struct free_block_type *forehand,*pre,*rear; int i; if(head== NULL) return -1; for(i= 0;i< free_block_count-1;i++) { forehand= head; pre= forehand->next; rear= pre->next; while(pre->next!= NULL) { if(forehand== head&&forehand->size>= pre->size) { //比较空闲链表中第一个空闲块与第二个空闲块空间的大小 head->next= pre->next; pre->next= head; head= pre; forehand= head->next; pre= forehand->next; rear= pre->next; } else if(pre->size>= rear->size) { //比较链表中其它相邻两个结点的空间的大小 pre->next= rear->next; forehand->next= rear; rear->next= pre; forehand= rear; rear= pre->next; } else { forehand= pre; pre= rear; rear= rear->next; } } } return 0; }
3. 内存分配算法
First Fit:从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法的目的在于减少查找时间。
为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,
在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。
int allocate_FF(struct allocated_block *ab)//first fit { int ret; struct free_block_type *pre= NULL,*ff= free_block; if(ff== NULL) return -1; while(ff!= NULL) { if(ff->size>= ab->size) { ret= allocate(pre,ff,ab); break; } pre= ff; pre= pre->next; } if(ff== NULL&¤t_free_mem_size> ab->size) ret= mem_retrench(ab); else ret= -2; rearrange_FF(); return ret; }
Best Fit:从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使
碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一
个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。
int allocate_BF(struct allocated_block *a)//best fit { int ret; struct free_block_type *pre= NULL,*bf= free_block; if(bf== NULL) return -1; while(bf!= NULL) { if(bf->size>= ab->size) { ret= allocate(pre,bf,ab); break; } pre= bf; pre= pre->next; } if(bf== NULL&¤t_free_mem_size> ab->size) ret= mem_retrench(ab); else ret= -2; rearrange_BF(); return ret; }
Worst Fit:从全部空闲区中找出能满足作业要求的、且大小最大的空闲分区,从而使链表中
的结点大小趋于均匀,适用于请求分配的内存大小范围较窄的系统。为适应此算法,空闲分区表(空闲区链)中的空
闲分区按大小从大到小进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留小的空闲区,尽量
减少小的碎片产生。
int allocate_WF(struct allocated_block *ab)//worst fit { int ret; struct free_block_type *wf= free_block; if(wf== NULL) return -1; if(wf->size>= ab->size) allocate(NULL,wf,ab); else if(current_free_mem_size>= ab->size) ret= mem_retrench(ab); else ret= -2; rearrange_WF(); return ret; }
4. 内存释1放算法
清除输入pid的进程,首先定义后声明pid,根据链表查找pid,随后进行free释放内存和数据,并且返还给未使用的内存大小中
void kill_process() //清楚当前pid的进程 { struct allocated_block *ab; int pid; printf("Kill Process,pid="); scanf("%d",&pid); getchar(); ab= find_process(pid); if(ab!= NULL) { free_mem(ab); //释放ab所表示的分配区 dispose(ab); //释放ab数据结构结点 } }
//将ab所表示的已分配区归还,并进行可能的合并 int free_mem(struct allocated_block *ab) { int algorithm= ma_algorithm; struct free_block_type *fbt,*pre,*work; fbt= (struct free_block_type*)malloc(sizeof(struct free_block_type)); if(!fbt) return -1; pre= free_block; fbt->start_addr= ab->start_addr; fbt->size= ab->size; fbt->next= NULL; if(pre!= NULL) { while(pre->next!= NULL) pre= pre->next; pre->next= fbt; } else { free_block= fbt; } rearrange_FF(); pre= free_block; work= pre->next; while(work!= NULL) { if(pre->start_addr+ pre->size== work->start_addr) { pre->size+= work->size; free(work); work= pre->next; } else { pre= work; work= work->next; } } current_free_mem_size+= ab->size; return 1; }
5. 运行结果
(1)产生测试数据
写程序,产生测试数据(随机)。给出你的源码,以及你生成的测试数据是什么。
随机为3个进程分配、释放内存10次以上,即随机产生10组以上数据:(进程Pi 分配内存大小) 或者 (进程Pi结束)
此处为实验测试的main函数
int main() { free_block= init_free_block(mem_size); printf("请选择内存分配算法\n"); printf("1:首次适应算法\n"); printf("2:最佳适应算法\n"); printf("3:最差适应算法\n"); char choose; fflush(stdin); choose= getchar(); getchar(); switch (choose) { case '1': rearrange(1); break; case '2': rearrange(2); break; case '3': rearrange(3); break; } int count; printf("ps:内存大小自动定为50-100,所以输入的进程次数尽量少于10!\n"); printf("算法已经分配完成,请输入要创建的进程次数:"); scanf("%d",&count); int pid= 0; int i; for(i=0;i<count;i++){ create_process();//添加新进程 showmemuse();//显示内存使用情况 } while(1) { printf("是否要删除进程?(输入no退出本程序)y/n:"); fflush(stdin); choose= getchar(); if(choose=='y') { kill_process(); count--; showmemuse(); } else break; } }
(2)解释结果
中间不截了
删除进程 5
可以看到进程5没了,
然后退出程序。