記憶體分配演算法-(首次分配法和最佳分配法)
阿新 • • 發佈:2019-02-19
/* implement a memory allocation scheme by using algorithms first-fit, next-fit, and best-fit * freelist為空閒區連結串列的頭,它的下一個節點才指向空閒緩衝區 * freelist是按首地址來排序的,而不是按size來排序。按首地址排序便於相鄰空閒記憶體合併;按size大小來排序,便於分配記憶體 */ #include<stdio.h> #include<stdlib.h> #define N 100 typedef enum {FALSE, TRUE} bool; typedef struct node { char *ptr; //start addr 指向mem處開始的地址 int size; //size of the free block struct node *next; //next free block }node; char mem[N]; //total memory pool node freelist; //head of free list, no value /* init freelist to contain the whole mem */ void init() { node *ptr = (node *)malloc(sizeof(node)); ptr->ptr = mem; ptr->size = N; ptr->next = NULL; freelist.next = ptr; } /* remove a node ptr from the list whose previous node is prev */ void removenode(node *ptr, node *prev) { prev->next = ptr->next; free(ptr); } /* 首次適配法:從自由空閒區中選取第一個合適空閒區來分配 * 返回分配記憶體區首地址 */ char *firstfit(int size) { node *ptr, *prev; char *memptr; for(prev=&freelist, ptr=prev->next; ptr; prev=ptr, ptr=ptr->next) if(ptr->size > size) { memptr = ptr->ptr; ptr->size -= size; //從空閒區去掉size空間 ptr->ptr += size; //空閒區首地址往後移size個單位 return memptr; //返回申請到的空閒區 首地址 } else if(ptr->size = size) { memptr = ptr->ptr; removenode(ptr, prev); return memptr; } return NULL; //沒有足夠長的空閒記憶體 } /* 最佳適配法:找到大小與size最接近的空閒區來分配 */ char *bestfit(int size) { node *ptr, *prev; char *memptr; int minwaste = N+1; node *minptr = NULL, *minprev; for(prev=&freelist, ptr=prev->next; ptr; prev=ptr, ptr=ptr->next) if(ptr->size >= size && ptr->size-size < minwaste) { minwaste = ptr->size - size; minptr = ptr; minprev = prev; } if(minptr == NULL)//沒有找到 return NULL; ptr = minptr; prev = minptr; if(ptr->size > size) { memptr = ptr->ptr; ptr->size -= size; ptr->ptr += size; return memptr; } else if(ptr->size == size) { memptr = ptr->ptr; removenode(ptr, prev); return memptr; } return NULL; } /* add memptr of size to freelist, remember that block ptrs are stored on mem addr */ void addtofreelist(char *memptr, int size) { node *prev, *ptr, *newptr; for(prev=&freelist, ptr=prev->next; ptr && ptr->ptr < memptr; prev=ptr, ptr=ptr->next) ; newptr = (node *)malloc(sizeof(node)); newptr->ptr = memptr; newptr->size = size; newptr->next = ptr; prev->next = newptr; } /* combine adj blocks of list if necessary */ void coalesce() { node *prev, *ptr; for(prev=&freelist, ptr=prev->next; ptr; prev=ptr, ptr=ptr->next) if(prev != &freelist && prev->ptr+prev->size == ptr->ptr) { prev->next = ptr->next; free(ptr); ptr = prev; } } /* prt: sizeof(int) contains size of the pool allocated * 返回分配的空間首地址(不包括最前面的長度的4個位元組) */ char *memalloc(int size) { char *ptr = firstfit(size + sizeof(int)); //此處選擇分配演算法 printf("allocating %d using firstfit...\n", size); if(ptr == NULL) return NULL; *(int *)ptr = size; //分配的空閒記憶體區前面幾個位元組用於存放分配數 return ptr+sizeof(int); } void memfree(char *ptr) { int size = *(int *)(ptr-sizeof(int));//找到已分配的空閒區大小(空閒區的前4個位元組) printf("freeing %d...\n", size); addtofreelist(ptr-sizeof(int), size+sizeof(int)); coalesce(); } void printfreelist() { node *ptr; printf("\t"); for(ptr=freelist.next; ptr; ptr=ptr->next) printf("{%u %d}", ptr->ptr, ptr->size); putchar('\n'); } main() { char *p1, *p2, *p3, *p4, *p5; init(); printfreelist(); p1 = memalloc(10);//note:分配10個位元組,但其前面還有4個位元組用於指示長度的,所以共用了14位元組 printfreelist(); p2 = memalloc(15); printfreelist(); p3 = memalloc(23); printfreelist(); p4 = memalloc(3); printfreelist(); p5 = memalloc(8); printfreelist(); memfree(p1); printfreelist(); memfree(p5); printfreelist(); memfree(p3); printfreelist(); p1 = memalloc(23); printfreelist(); p1 = memalloc(23); printfreelist(); memfree(p2); printfreelist(); p1 = memalloc(3); printfreelist(); memfree(p4); printfreelist(); p2 = memalloc(1); printfreelist(); memfree(p1); printfreelist(); memfree(p2); printfreelist(); return 0; }