動態分區分配是根據進程的實際需要,動態的為之分配內存空間。而在實現可變分區分配時,將涉及到分區分配中
所用的數據結構、分區分配算法和分區的分配與內存回收的過程。
分區分配中的數據結構:(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; } } }
