内存分配---FF、BF、WF三种算法
动态分区分配是根据进程的实际需要,动态的为之分配内存空间。而在实现可变分区分配时,将涉及到分区分配中
所用的数据结构、分区分配算法和分区的分配与内存回收的过程。
分区分配中的数据结构:(1)描述空闲块的数据结构。(2)内存块的描述。
#define PROCESS_NAME_LEN 32 //进程名长度 #define MIN_SLICE 10 //最小碎片的大小 #define DEFAULT_MEM_SIZE 1024 //内存大小 #define DEFAULT_MEM_START 0 //起始位置 //内存分配算法 #define MA_FF 1 #define MA_BF 2 #define MA_WF 3 //描述每一个空闲块的数据结构 struct free_block_type { int size; //空闲块大小 int start_addr; //空闲块起始位置 struct free_block_type *next; //指向下一个空闲块 }; //指向内存中空闲块链表的首地址 struct free_block_type *free_block= NULL; //每个进程分配到的内存块的描述 struct allocated_block { int pid; int size; //进程大小 int start_addr; //进程分配到的内存块的起始地址 char process_name[PROCESS_NAME_LEN]; //进程名 struct allocated_block *next; //指向下一个进程控制块 }; //进程分配内存块链表的首指针 struct allocated_block *allocated_block_head= NULL; int free_block_count= 0; //空闲块的个数 int mem_size= DEFAULT_MEM_SIZE; //内存大小 int current_free_mem_size= 0; //当前空闲内存大小 int ma_algorithm= MA_FF; //当前分配算法 static int pid= 0; int flag= 0; //设置内存大小标志,表示内存大小是否设置
分区分配算法:
(1)首次适应算法(First Fit):从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给
作业,这种方法的目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到
高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。
(2)最佳适应算法(Best Fit):从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使
碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一
个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。
(3)最差适应算法(Worst Fit):从全部空闲区中找出能满足作业要求的、且大小最大的空闲分区,从而使链表中
的结点大小趋于均匀,适用于请求分配的内存大小范围较窄的系统。为适应此算法,空闲分区表(空闲区链)中的空
闲分区按大小从大到小进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留小的空闲区,尽量
减少小的碎片产生。
下面是进行以上三种算法的实现:
#include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <unistd.h> #define PROCESS_NAME_LEN 32 //进程名长度 #define MIN_SLICE 10 //最小碎片的大小 #define DEFAULT_MEM_SIZE 1024 //内存大小 #define DEFAULT_MEM_START 0 //起始位置 //内存分配算法 #define MA_FF 1 #define MA_BF 2 #define MA_WF 3 //描述每一个空闲块的数据结构 struct free_block_type { int size; //空闲块大小 int start_addr; //空闲块起始位置 struct free_block_type *next; //指向下一个空闲块 }; //指向内存中空闲块链表的首地址 struct free_block_type *free_block= NULL; //每个进程分配到的内存块的描述 struct allocated_block { int pid; int size; //进程大小 int start_addr; //进程分配到的内存块的起始地址 char process_name[PROCESS_NAME_LEN]; //进程名 struct allocated_block *next; //指向下一个进程控制块 }; //进程分配内存块链表的首指针 struct allocated_block *allocated_block_head= NULL; int free_block_count= 0; //空闲块的个数 int mem_size= DEFAULT_MEM_SIZE; //内存大小 int current_free_mem_size= 0; //当前空闲内存大小 int ma_algorithm= MA_FF; //当前分配算法 static int pid= 0; int flag= 0; //设置内存大小标志,表示内存大小是否设置 struct free_block_type* init_free_block(int mem_size); void display_menu(); int set_mem_size(); void set_algorithm(); void rearrange(int algorithm); int rearrange_WF(); int rearrange_BF(); int rearrange_FF(); int new_process(); int allocate_mem(struct allocated_block *ab); void kill_process(); int free_mem(struct allocated_block *ab); int dispose(struct allocated_block *free_ab); int display_mem_usage(); struct allocated_block* find_process(int pid); int do_exit(); int allocate_FF(struct allocated_block *ab); int allocate_BF(struct allocated_block *ab); int allocate_WF(struct allocated_block *ab); int allocate(struct free_block_type *pre,struct free_block_type *allocate_free_nlock,struct allocated_block *ab); int mem_retrench(struct allocated_block *ab); //通过内存紧缩技术给新进程分配内存空间 int mem_retrench(struct allocated_block *ab) { struct allocated_block *allocated_work,*allocated_pre= allocated_block_head; struct free_block_type *free_work,*free_pre= free_block->next; if(allocated_pre== NULL) return -1; allocated_pre->start_addr= 0; allocated_work= allocated_pre->next; while(allocated_work!= NULL) { allocated_work->start_addr= allocated_pre->start_addr+ allocated_pre->size; allocated_pre= allocated_work; allocated_work= allocated_work->next; } free_block->start_addr= allocated_pre->start_addr+ allocated_pre->size; free_block->size= current_free_mem_size; free_work= free_pre; while(free_pre!= NULL) { free(free_pre); free_pre= free_work; if(free_pre!= NULL) free_work= free_work->next; } allocate(NULL,free_block,ab); return 1; } //给新进程分配内存空间 int allocate(struct free_block_type *pre,struct free_block_type *allocate_free_block,struct allocated_block *ab) { struct allocated_block *p= allocated_block_head; ab->start_addr= allocate_free_block->start_addr; if(allocate_free_block->size-ab->size< MIN_SLICE) { ab->size= allocate_free_block->size; if(pre!= NULL) { pre->next= allocate_free_block; } else { free_block= allocate_free_block->next; } free(allocate_free_block); } else { allocate_free_block->start_addr+= ab->size; allocate_free_block->size-= ab->size; } if(p== NULL) { allocated_block_head= ab; } else { while(p->next!= NULL) p= p->next; p->next= ab; } current_free_mem_size-= ab->size; if(current_free_mem_size== 0) free_block= NULL; return 0; } //按照最坏适应算法给新进程分配内存空间 int allocate_WF(struct allocated_block *ab) { 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; } //按照最佳适应算法给新进程分配内存空间 int allocate_BF(struct allocated_block *ab) { 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; } //按照首次适应算法给新进程分配内存空间 int allocate_FF(struct allocated_block *ab) { 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; } //分配内存模块 int allocate_mem(struct allocated_block *ab) { int ret; struct free_block_type *fbt,*pre; int request_size= ab->size; fbt= pre= free_block; switch(ma_algorithm) { case MA_FF: ret= allocate_FF(ab); break; case MA_BF: ret= allocate_BF(ab); break; case MA_WF: ret= allocate_WF(ab); break; default: break; } return ret; } //创建一个新进程 int new_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,"PROCESS-%02d",pid);//将格式化的数据写入某字符串中 ab->pid= pid; printf("Memory for %s:",ab->process_name); for(;;) { scanf("%d",&size); getchar(); 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 do_exit() { struct allocated_block *allocated_ab,*allocated_pre; struct free_block_type *free_ab,*free_pre; free_pre= free_block; allocated_pre= allocated_block_head; if(free_pre!= NULL) { free_ab= free_pre->next; while(free_ab!= NULL) { free(free_pre); free_pre= free_ab; free_ab= free_ab->next; } } if(allocated_pre!= NULL) { allocated_ab= allocated_pre->next; while(allocated_ab!= NULL) { free(allocated_pre); allocated_pre= allocated_ab; allocated_ab= allocated_ab->next; } } allocated_ab= allocated_ab->next; return 0; } //在进程分配链表中寻找指定进程 struct allocated_block* find_process(int pid) { struct allocated_block *ab= allocated_block_head; if(ab== NULL) { printf("Here?111\n"); return NULL; } while(ab->pid!= pid&&ab->next!= NULL) ab= ab->next; if(ab->next== NULL&&ab->pid!= pid) { printf("Here?222\n"); return NULL; } return ab; } //显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 int display_mem_usage() { struct free_block_type *fbt= free_block; struct allocated_block *ab= allocated_block_head; 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("\nUsed 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"); return 1; } //释放ab数据结构结点 int dispose(struct allocated_block *free_ab) { struct allocated_block *pre,*ab; if(free_block== NULL) return -1; if(free_ab== allocated_block_head) //如果要释放第一个结点 { allocated_block_head= allocated_block_head->next; free(free_ab); } else { pre= allocated_block_head; ab= allocated_block_head->next; //找到free_ab while(ab!= free_ab) { pre= ab; ab= ab->next; } pre->next= ab->next; free(ab); } return 1; } //将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; } //删除进程,归还分配的存储空间,并删除描述该进程内存分配的结点 void kill_process() { 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数据结构结点 } } //按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算法重新整理内存空闲块链表,按空闲块大小从小到大排序 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; } //按指定的算法整理内存空闲块链表 void rearrange(int algorithm) { switch(algorithm) { case MA_FF: rearrange_FF(); break; case MA_BF: rearrange_BF(); break; case MA_WF: rearrange_WF(); break; } } //设置当前的分配算法 void set_algorithm() { int algorithm; //system("clear"); printf("\t1-First Fit\n"); //首次适应算法 printf("\t2-Best Fit\n"); //最佳适应算法 printf("\t3-Worst Fit\n"); //最坏适应算法 printf("Please choose(1-3):"); for(;;) { scanf("%d",&algorithm); getchar(); if(algorithm>= 1&&algorithm<= 3) { ma_algorithm= algorithm; break; } else { printf("\nCannot input %d,Please input 1-3:",algorithm); } } rearrange(ma_algorithm); } //设置内存的大小 int set_mem_size() { int size; if(flag!= 0) //防止重复设置 { printf("Cannont set memory size again\n"); return 0; } printf("Total memory size="); for(;;) { scanf("%d",&size); getchar(); if(size> 0) { current_free_mem_size= size; mem_size= size; free_block->size= mem_size; break; } else { printf("The size must greater than zero!Please input again:"); } } flag= 1; //内存大小已经设置 return 1; } //显示主菜单 void display_menu() { printf("\n"); //system("clear"); printf("1-Set memory size(default= %d)\n",DEFAULT_MEM_SIZE); printf("2-Select memory allocation algorithm\n"); printf("3-New process\n"); printf("4-Terminate a process\n"); printf("5-Display memory usage\n"); printf("0-Exit\n"); } //初始化空闲块,默认为一块,可以指定大小及起始地址 struct free_block_type* init_free_block(int mem_size) { struct free_block_type *fb; fb= (struct free_block_type*)malloc(sizeof(struct free_block_type)); if(fb== NULL) { printf("No mem\n"); return NULL; } current_free_mem_size= mem_size; fb->size= mem_size; fb->start_addr= DEFAULT_MEM_START; fb->next= NULL; //首地址指向NULL return fb; } int main() { char choice; pid= 0; free_block= init_free_block(mem_size); while(1) { display_menu(); fflush(stdin); choice= getchar(); getchar(); switch(choice) { case '1': //设置内存大小 set_mem_size(); break; case '2': //设置算法 set_algorithm(); flag= 1; break; case '3': //创建新进程 new_process(); flag= 1; break; case '4': //删除进程 kill_process(); flag= 1; break; case '5': //显示内存使用 display_mem_usage(); flag= 1; break; case '0': //释放链表并退出 do_exit(); exit(0); default: break; } } }