1. 程式人生 > >可變分割槽儲存管理(最先、下次、最佳、最差適配法)

可變分割槽儲存管理(最先、下次、最佳、最差適配法)

可變分割槽儲存管理,又稱動態分割槽模式,是實存管理中連續儲存的一種實現方式。
在分割槽的分配和回收時,根據不同的查詢規則,有5種:

  • first fit,最先適應分配演算法,按地址遞增排序。
  • next fit,下次適應分配演算法,在first fit基礎上,從上次搜尋結束為止開始搜尋。
  • best fit,最佳適應分配演算法,按空閒區長度從大到小排序。
  • worst fit,最壞適應分配演算法,按空閒區長度遞減排序。
  • quick fit,快速適應分配演算法,將常用長度的空閒區有組織地存放。

這裡以一份程式碼來演示最先適配法,下次適配法,最佳和最差適配法。原始檔命名為variable_partition.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define JOB_MAX 10
struct
{
    int address;
    int length;
    int id;
}used_table[JOB_MAX];

struct f_table
{
    int address;
    int length;
}free_table[JOB_MAX+1];

int free_num = 1;
int used_num = 0;
int comp_addr_increase(const void *p1
, const void *p2) { return ((struct f_table*)p1)->address - ((struct f_table*)p2)->address; } int comp_length_increase(const void *p1, const void *p2) { return ((struct f_table*)p1)->length - ((struct f_table*)p2)->length; } int comp_length_decrease(const void *p1, const void *p2
) { return ((struct f_table*)p2)->length - ((struct f_table*)p1)->length; } int update_free_table() { int i, j; if(free_num < 2) return 0; /* sort by address */ qsort(free_table, free_num, sizeof free_table[0], comp_addr_increase); /* merge */ for(i=0; i < free_num-1; i ++) { if(free_table[i].address + free_table[i].length == free_table[i+1].address) { free_table[i].length += free_table[i+1].length; for(j = i+1; j < free_num-1; j ++) { memcpy(&free_table[j], &free_table[j+1], sizeof free_table[0]); } free_num --; i --; } } /* sort by length if necessary */ #if defined( BEST_FIT ) qsort(free_table, free_num, sizeof free_table[0], comp_length_increase); #elif defined( WORST_FIT ) qsort(free_table, free_num, sizeof free_table[0], comp_length_decrease); #endif return 0; } int show() { int i=0; printf(".-----------------------------------\n"); printf("| free table:\n"); if(free_num) { printf("|%10s %10s\n", "Address", "Length"); for(i=0; i<free_num; i ++) { printf("|%10d %10d\n", free_table[i].address, free_table[i].length); } } else { printf("| no free table now!\n"); } printf("|-----------------------------------\n"); printf("| used table:\n"); if(used_num) { printf("|%10s %10s %5s\n", "Address", "Length","pid"); for(i=0; i<used_num; i ++) { printf("|%10d %10d %5d\n", used_table[i].address, \ used_table[i].length, used_table[i].id); } } else { printf("|No job running now!\n"); } printf(".-----------------------------------\n"); return 0; } /* return task id if no error * return -1 if no space for new task */ int allocate(int size) { static int next_pid = 1; static int next_fit_pos = 0; int n; int i; if(used_num >= JOB_MAX || free_num < 1) return -1; #if defined( NEXT_FIT ) for(i = (next_fit_pos+1)%free_num, n = free_num; \ n > 0; \ i = (i+1)%free_num, n--) #else for(i= 0; i<free_num; i ++) #endif { if(size <= free_table[i].length) { used_table[used_num].id = next_pid ++; used_table[used_num].address = free_table[i].address; used_table[used_num].length = size; free_table[i].address += size; free_table[i].length -= size; #if defined( NEXT_FIT ) next_fit_pos = i; #endif if(0 == free_table[i].length) { /* delete this free item */ for(; i<free_num; i ++) { memcpy(&free_table[i], &free_table[i+1], sizeof free_table[0]); } free_num --; } used_num ++; update_free_table(); return next_pid-1; } } /* no enough size */ return -1; } /* * return -1 if no such job * return 0 if no error */ int reclaim(int pid) { int i; if(0 == used_num) return -1; for(i=0; i < used_num; i ++) { if(used_table[i].id == pid) { free_table[free_num].address = used_table[i].address; free_table[free_num].length = used_table[i].length; free_num ++; update_free_table(); for(; i< used_num; i ++) { memcpy(&used_table[i], &used_table[i+1], sizeof used_table[0]); } used_num --; return 0; } } return -1; } int main() { int input = 0; int pid; int size; int ret; free_table[0].address = 40000; free_table[0].length = 1000; show(); while(1) { printf("0-quit 1-allocate 2-reclaim input:"); fflush(stdout); scanf("%d", &input); switch(input) { case 0: exit(1); case 1: printf("please input task size:"); fflush(stdout); scanf("%d", &size); pid = allocate(size); if(pid > 0) { printf("job #%d is running\n", pid); show(); } else { printf("job cannot run\n"); } break; case 2: printf("please input the task id:"); fflush(stdout); scanf("%d", &pid); ret = reclaim(pid); if(ret) { printf("no such job\n"); } else { printf("job #%d reclaimed.\n", pid); show(); } break; default: printf("no such choice\n"); } } return 0; }

對應的Makefile如下:

SOURCE_FILES = variable_partition.c
N=100

all:f n b w

f: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o firstfit -DJOB_MAX=$N

n: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o nextfit -DNEXT_FIT -DJOB_MAX=$N

b: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o bestfit -DBEST_FIT -DJOB_MAX=$N

w: $(SOURCE_FILES)
    gcc $(SOURCE_FILES) -o worstfit -DWORST_FIT -DJOB_MAX=$N

clean:
    rm -f  firstfit nextfit bestfit worstfit

需要說明的是,用陣列來儲存空閒區和非空閒區,在next fit中,由於遍歷的位置記錄的是空閒區的陣列下標,所以當新空閒區插入時,會從新插入的分割槽開始遍歷。如果想要嚴格地實現“從上次遍歷結束得位置”開始搜尋,可以記錄下空閒區起始地址,然後通過地址來判斷next fit的起始地址。