不考虑性能的内存管理模拟系统(假内存)的C语言实现

#include<stdio.h>           /*头文件*/

 

#define PROCESS_NAME_LEN 32   /*进程名长度*/

#define MIN_SLICE    10             /*最小碎片的大小*/

#define DEFAULT_MEM_SIZE 1024     /*内存大小*/

#define DEFAULT_MEM_START 0       /*起始位置*/

 

#define FF 1             /*首次适应*/

#define BF 2             /*最佳适应*/

#define WF 3             /*最坏适应*/

 

int mem_size = DEFAULT_MEM_SIZE;        /*内存大小*/

int manage_algorithm = FF;           /*当前分配算法*/

static int pid = 0;              /*初始pid*/

int flag = 0;              /*内存是否已设置标志*/

 

/*********************************************************/

typedef struct free_block{     /*描述每一个空闲块的数据结构*/

    int size;               /*空闲块大小*/

    int start_addr;             /*起始地址*/

    struct free_block* next;    /*下一个空闲块的指针*/

}free_block; 

 

free_block* head_of_free_block = NULL; //指向内存中空闲块链表的首指针

 

/*********************************************************/

typedef struct allocated_block{     /*进程已分配的内存块的描述*/

    int pid;                    /*所占进程的标识符*/

    int size;                       /*块大小*/

    int start_addr;           /*起始地址*/

    char process_name[PROCESS_NAME_LEN];    /*进程名*/

    struct allocated_block *next;       /*下一个分配快*/

}allocated_block;

 

allocated_block* head_of_allocated_block = NULL;    /*进程分配内存块链表的首指针*/

 

/*********************************************************/

free_block* init_free_block(int);       //初始化空闲区

void display_menu(void);        //显示菜单

int set_mem_size(void);          //设置内存大小

void set_algorithm(void);       //设置算法

void rearrange(int);        //重排链表

void rearrange_FF(void);        //首次重排

void rearrange_BF(void);        //最佳重排

void rearrange_WF(void);        //最坏重排

int new_process(void);          //创建新进程

int allocate_mem(allocated_block*); //分配内存

void rearrange_Allocated(void);     //进程链排序

void kill_process(void);        //删除进程

allocated_block* find_process(int pid); //查找块位置

int dispose(allocated_block*);  //块归还

int free_mem(allocated_block*); //释放内存

int display_mem_usage(void);        //显示内存使用

void do_exit(void);         //释放链表并退出

 

/*********************************************************/

int main(void){

    char choice;      /*选择的功能*/

    pid = 0;            /*初始化pid*/

    head_of_free_block = init_free_block(mem_size); //初始化空闲区

    while(1){

        display_menu(); //显示菜单

        fflush(stdin);

        choice = getchar(); //获取用户输入

        switch(choice){

            case '1':set_mem_size();break;  //设置内存大小

            case '2':set_algorithm();break;//设置算法

            case '3':new_process();break;//创建新进程

            case '4':kill_process();break;//删除进程

            case '5':display_mem_usage();break; //显示内存使用

            case '0':do_exit();exit(0); //释放链表并退出

            default:printf("ErrorInput_Exception\n");break;     

        }

    }

}

 

/*********************************************************/

/*初始化空闲块,默认为一块,可以指定大小及起始地址*/

free_block* init_free_block(int mem_size){

    free_block* fb = NULL;

 

    fb = (free_block*)malloc(sizeof(free_block));

    if(fb==NULL){

        printf("MemoryOverFlow_Exception\n");

        return NULL;

    }

    fb->size = mem_size;

    fb->start_addr = DEFAULT_MEM_START;

    fb->next = NULL;

    return fb;

}

 

/*********************************************************/

/*显示菜单*/

void display_menu(void){

    printf("\n");

    printf("1 - Set memory size (default=%d,current=%d)\n",DEFAULT_MEM_SIZE,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");

}

 

/*********************************************************/

/*设置内存的大小*/

int set_mem_size(void){

    int size;

    if(flag!=0){        //防止重复设置

        printf("Cannot set memory size again\n");

        return 0;

    }

    printf("Total memory size = ");

    scanf("%d",&size);

    if(size>0){

        mem_size = size;

        head_of_free_block->size = mem_size;

        flag = 1;

    }

    else printf("SizeSetNoLegal_Exception\n");

    return 1;

}

 

/*********************************************************/

/* 设置当前的分配算法 */

void set_algorithm(void){

    int algorithm;

    printf("\t1 - First Fit\n");

    printf("\t2 - Best Fit \n");

    printf("\t3 - Worst Fit \n");

    scanf("%d",&algorithm);

    if(algorithm >= 1 && algorithm <= 3)

        manage_algorithm = algorithm;

    else{

        printf("NoSuchAlgorithm_Exception\n");

        return -1;

    }

    flag = 1;

    rearrange(manage_algorithm);    //按指定算法重新排列空闲区链表

}

 

/*********************************************************/

/*按指定的算法整理内存空闲块链表*/

void rearrange(int algorithm){

    switch(algorithm){

        case FF:rearrange_FF();break;

        case BF:rearrange_BF();break;

        case WF:rearrange_WF();break;

    }

}

 

/*********************************************************/

/*按FF算法重新整理内存空闲块链表*/

void rearrange_FF(void){  

    free_block* fb;                 //内循环

    free_block* temp;                       //外循环

    int size;

    int start_addr;                              

    for(temp = head_of_free_block;temp != NULL;temp = temp->next){

        for(fb = temp->next;fb != NULL;fb = fb->next){

            if(temp->start_addr > fb->start_addr){

                size = temp->size;

                start_addr = temp->start_addr;

                temp->size = fb->size;

                temp->start_addr = fb->start_addr;

                fb->size = size;

                fb->start_addr = start_addr;

            }

        }

    }

}

 

/*********************************************************/

/*按BF算法重新整理内存空闲块链表*/

void rearrange_BF(void){

    free_block* fb;                 //内循环

    free_block* temp;                       //外循环

    int size;

    int start_addr;                         

    for(temp = head_of_free_block;temp != NULL;temp = temp->next){

        for(fb = temp->next;fb != NULL;fb = fb->next){

            if(temp->size > fb->size){

                size = temp->size;

                start_addr = temp->start_addr;

                temp->size = fb->size;

                temp->start_addr = fb->start_addr;

                fb->size = size;

                fb->start_addr = start_addr;

            }

        }

    }

}

 

/*********************************************************/

/*按WF算法重新整理内存空闲块链表*/

void rearrange_WF(void){

    free_block* fb;                 //内循环

    free_block* temp;                       //外循环

    int size;

    int start_addr;                             

    for(temp = head_of_free_block;temp != NULL;temp = temp->next){

        for(fb = temp->next;fb != NULL;fb = fb->next){

            if(temp->size < fb->size){

                size = temp->size;

                start_addr = temp->start_addr;

                temp->size = fb->size;

                temp->start_addr = fb->start_addr;

                fb->size = size;

                fb->start_addr = start_addr;

            }

        }

    }

}

 

/*********************************************************/

/*创建新的进程,主要是获取内存的申请数量*/

int new_process(void){

    allocated_block* ab;

    int size;   

    ab=(allocated_block*)malloc(sizeof(allocated_block));

    if(!ab) exit(-5);

    ab->next = NULL;

    pid++;

    sprintf(ab->process_name, "PROCESS-%02d\0", pid);

    ab->pid = pid;   

    printf("Memory for %s:", ab->process_name);

    scanf("%d", &size);

    if(size>0) ab->size = size;

    else{

        printf("SizeNotLegal_Exception\n");

        pid--;

        return -1;

    }

 

    ab->start_addr = allocate_mem(ab);          /* 从空闲区分配内存,ab->start_addr表示分配地址,-1表示未成功*/

 

    if((ab->start_addr != -1) && (head_of_allocated_block == NULL)){    /*如果此时head_of_allocated_block尚未赋值,则赋值*/

        head_of_allocated_block = ab;

        flag = 1;

        return 1;       

    }

    else if (ab->start_addr != -1){     /*分配成功,将该已分配块的描述插入已分配链表,头插法*/

        ab->next = head_of_allocated_block;

        head_of_allocated_block = ab;

        flag = 1;

        return 2;       

    }

    else if(ab->start_addr == -1){          /*分配不成功*/

        printf("AllocationFail_Exception\n");

        free(ab);

        return -2;      

    }

    return 3;

}

 

/*********************************************************/

/*分配内存模块*/

int allocate_mem(allocated_block* ab){

    free_block *now, *pre;

    int request_size = ab->size;

    now = pre = head_of_free_block;

    double temp;

    int sum_size = 0;

    // 1. 找到可满足空闲分区且分配后剩余空间足够大,则分割

    // 2. 找到可满足空闲分区且但分配后剩余空间比较小,则一起分配

    // 3. 找不可满足需要的空闲分区但空闲分区之和能满足需要,则采用内存紧缩技术,进行空闲分区的合并,然后再分配

    // 4. 在成功分配内存后,应保持空闲分区按照相应算法有序

    // 5. 分配成功则返回分配首地址,否则返回-1

    while(now != NULL){

        sum_size = sum_size + now->size;

        if(request_size <= now->size){

            temp = (double)(now->size-request_size)/(double)now->size;

            if(temp <= 0.1){        //剩余空间小于百分之十

                int addr = now->start_addr;

                if(head_of_free_block->next == NULL){

                    ab->size = head_of_free_block->size;

                    head_of_free_block = NULL;

                }

                else{

                    if(now == head_of_free_block){

                        ab->size = head_of_free_block->size;

                        head_of_free_block = head_of_free_block->next;

                    }

 

                    else{

                        ab->size = now->size;

                        pre->next = now->next;

                    }

                }

                return addr;

            }

            else{                   //剩余空间大于百分之十

                int addr = now->start_addr;         //分配

                now->start_addr = now->start_addr + request_size;

                now->size = now->size - request_size;   //减少内存

                switch(manage_algorithm){       //管理重排

                    case FF:rearrange_FF();break;

                    case BF:rearrange_BF();break;

                    case WF:rearrange_WF();break;

                }

                return addr;

            }

        }

        pre = now;

        now = now->next;

    }

    if(sum_size < request_size) return -1;

    else{           //内存紧缩技术

        rearrange_Allocated();      //进程链排序

        allocated_block* abt = head_of_allocated_block;

        int size_T = 0;

        while(abt != NULL){

            abt->start_addr = size_T;

            size_T = size_T + abt->size;

            abt = abt->next;

        }

        free_block* fbt;

        while(head_of_free_block->next != NULL){    //空闲链合并

            fbt = head_of_free_block;

            head_of_free_block = head_of_free_block->next;

            free(fbt);

        }

        head_of_free_block->start_addr = size_T;

        head_of_free_block->size = sum_size;

 

        //分配

        int addr = head_of_free_block->start_addr;      //分配

        head_of_free_block->start_addr = head_of_free_block->start_addr + request_size;

        head_of_free_block->size = head_of_free_block->size - request_size; //减少内存

        return addr;

    }

    return 0;  

}

 

/*********************************************************/

/*对进程链地址排序*/

void rearrange_Allocated(void){  

    allocated_block* ab;                    //内循环

    allocated_block* temp;                      //外循环

 

    int pid;

    int size;

    int start_addr;

    char process_name[PROCESS_NAME_LEN];

 

    for(temp = head_of_allocated_block;temp != NULL;temp = temp->next){

        for(ab = temp->next;ab != NULL;ab = ab->next){

            if(temp->start_addr > ab->start_addr){

                pid = temp->pid;

                size = temp->size;

                start_addr = temp->start_addr;

                strcpy(process_name,temp->process_name);

 

                temp->pid = ab->pid;

                temp->size = ab->size;

                temp->start_addr = ab->start_addr;

                strcpy(temp->process_name,ab->process_name);

 

                ab->pid = pid;

                ab->size = size;

                ab->start_addr = start_addr;

                strcpy(ab->process_name,process_name);

            }

        }

    }

}

 

/*********************************************************/

/*删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点*/

void kill_process(void){

    allocated_block* ab;

    int pid;

    printf("Kill Process, pid=");

    scanf("%d", &pid);

    ab = find_process(pid);

    if(ab != NULL){

        flag = 1;

        free_mem(ab); /*释放ab所表示的分配区*/

        dispose(ab);  /*释放ab数据结构节点*/

    }

    else printf("NoSuchProcess_Exception\n");

}

 

/*********************************************************/

/*查找pid进程所在块*/

allocated_block* find_process(int pid){

    allocated_block* ab = head_of_allocated_block;

    while(ab != NULL){

        if(ab->pid == pid) break;

        ab = ab->next;

    }

    return ab;

}

 

/*********************************************************/

/*将ab所表示的已分配区归还,并进行可能的合并*/

int free_mem(allocated_block* ab){

    int algorithm = manage_algorithm;

    free_block *fb, *pre, *now;

    fb = (free_block*)malloc(sizeof(free_block));

    if(!fb) return -1;

    fb->size = ab->size;

    fb->start_addr = ab->start_addr;

    fb->next = NULL;

    // 1. 将新释放的结点插入到空闲分区队列末尾

    // 2. 对空闲链表按照地址有序排列

    // 3. 检查并合并相邻的空闲分区

    // 4. 将空闲链表重新按照当前算法排序

    if(head_of_free_block == NULL) head_of_free_block = fb;

    else{

        now = head_of_free_block;

        while(now->next != NULL) now = now->next;

        now->next = fb;

        rearrange_FF();

        pre = head_of_free_block;

        now = head_of_free_block->next;

        while(now != NULL){

            if((pre->start_addr + pre->size) == now->start_addr){

                fb = now;

                pre->size = pre->size + now->size;

                pre->next = now->next;

                free(fb);

                now = pre->next;

            }

            else{

                pre = now;

                now = now->next;

            }

        }

        switch(algorithm){      //管理重排

            case FF:rearrange_FF();break;

            case BF:rearrange_BF();break;

            case WF:rearrange_WF();break;

        }

    }

    return 1;

}

 

/*********************************************************/

/*释放ab数据结构节点*/

int dispose(allocated_block* free_ab){

    allocated_block *pre, *ab;

    if(free_ab == head_of_allocated_block){ /*如果要释放第一个节点*/

        head_of_allocated_block = head_of_allocated_block->next;

        free(free_ab);

        return 1;

    }

    pre = head_of_allocated_block; 

    ab = head_of_allocated_block->next;

    while(ab != free_ab){

        pre = ab; 

        ab = ab->next;

    }

    pre->next = ab->next;

    free(ab);

    return 2;

}

 

/*********************************************************/

/* 显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 */

int display_mem_usage(void){

    free_block* fbt = head_of_free_block;

    allocated_block* ab = head_of_allocated_block;

 

    printf("----------------------------------------------------------\n");

 

    /* 显示空闲区 */

    printf("Free Memory:\n");

    printf("%20s %20s\n", "      start_addr", "       size");

    if(fbt == NULL)

        printf("%20d %20d\n", -1, 0);

    else{

        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");

    flag = 1;

    return 0;

}

 

/*********************************************************/

/* 结束前的内存回收 */

void do_exit(void){

    free_block* fb = NULL;

    allocated_block* ab = NULL;

    while(head_of_free_block != NULL){

        fb = head_of_free_block;

        head_of_free_block = head_of_free_block->next;

        free(fb);

    }

    while(head_of_allocated_block != NULL){

        ab = head_of_allocated_block;

        head_of_allocated_block = head_of_allocated_block->next;

        free(ab);

    }

}

 

posted @ 2019-08-25 22:56  西兰花像棵小树  阅读(293)  评论(0编辑  收藏  举报