📜  内存管理中最差拟合算法程序(1)

📅  最后修改于: 2023-12-03 14:50:08.386000             🧑  作者: Mango

内存管理中最差适合算法程序介绍

本文介绍一种内存管理算法——最差适合算法,同时提供该算法的代码实现及相关解释。

算法原理

最差适合算法是一种动态分配存储器的算法,在该算法中,当需要分配一段内存空间时,将遍历空闲链表,查找最差、最大的空闲区。如果未找到足够大的空闲区,则将会对内存进行合并,直到找到能够满足请求的空闲区为止。

当释放内存空间时,将通过合并相邻的空闲区来创建更大的空闲区,同时更新空闲链表。

代码实现

下面是该算法的 C 代码实现,代码中包括注释以帮助理解。

#include <stdio.h>
#include <stdlib.h>

#define MAX_MEM_SIZE 10  // 内存大小为 10KB

// 进程控制块(PCB)
typedef struct pcb {
    int pid;             // 进程 ID
    int memory_size;     // 内存占用大小
    struct pcb* next;    // 链表指针
} PCB;

// 空闲链表结点
typedef struct free_node {
    int start_addr;      // 起始地址
    int end_addr;        // 结束地址
    struct free_node* next; // 链表指针
} FREE_NODE;

PCB* pcb_list = NULL;   // PCB 链表头指针

// 空闲链表头指针
FREE_NODE* free_list = NULL;

// 初始化空闲链表
void init_free_linklist() {
    // 将整个内存作为一块空闲区域
    FREE_NODE* free_block = (FREE_NODE*)malloc(sizeof(FREE_NODE)); 
    free_block->start_addr = 0;
    free_block->end_addr = MAX_MEM_SIZE*1024-1;
    free_block->next = NULL;
    free_list = free_block;
}

// 按进程的 ID 查找 PCB
PCB* find_pcb(int pid) {
    PCB* p = pcb_list;
    while(p != NULL) {
        if(p->pid == pid)
            return p;
        p = p->next;
    }
    return NULL;
}

// 创建 PCB
PCB* create_pcb(int pid, int size) {
    PCB* p = (PCB*)malloc(sizeof(PCB));
    p->pid = pid;
    p->memory_size = size;
    p->next = NULL;
    return p;
}

// 按起始地址查找空闲链表中的结点
FREE_NODE* find_free_node(int start_addr) {
    FREE_NODE* p = free_list;
    while(p != NULL) {
        if(p->start_addr == start_addr)
            return p;
        p = p->next;
    }
    return NULL;
}

// 分配内存
int malloc_pcb(int pid, int size) {
    if(size <= 0)       // 非法赋值
        return -1;
    if(find_pcb(pid) != NULL)  // PCB 已存在
        return -2;
    int start_addr = -1, end_addr = -1;
    int max_avail_size = -1;    // 最大可用内存
    FREE_NODE* p = free_list;
    FREE_NODE* max_avail_node = NULL;
    while(p != NULL) {          // 遍历空闲链表
        int avail_size = p->end_addr-p->start_addr+1;
        if(avail_size >= size && avail_size > max_avail_size) {
            max_avail_node = p;
            max_avail_size = avail_size;
        }
        p = p->next;
    }
    if(max_avail_node == NULL)   // 没有足够的内存,分配失败
        return -3;
    start_addr = max_avail_node->start_addr;
    end_addr = start_addr+size-1;
    if(max_avail_node->start_addr == start_addr) {    // 分配后,剩下的空闲区块(如果有)继续插入空闲链表
        max_avail_node->start_addr = end_addr+1;
        if(max_avail_node->start_addr > max_avail_node->end_addr) {
            if(max_avail_node == free_list)
                free_list = free_list->next;
            else {
                FREE_NODE* pre_node = free_list;
                while(pre_node->next != max_avail_node)
                    pre_node = pre_node->next;
                pre_node->next = max_avail_node->next;
            }
            free(max_avail_node);
        }
    } else if(max_avail_node->end_addr == end_addr) { // 同上,处理尾部
        max_avail_node->end_addr = start_addr-1;
    } else {
        FREE_NODE* new_node = (FREE_NODE*)malloc(sizeof(FREE_NODE));
        new_node->start_addr = end_addr+1;
        new_node->end_addr = max_avail_node->end_addr;
        new_node->next = max_avail_node->next;
        max_avail_node->end_addr = start_addr-1;
        max_avail_node->next = new_node;
    }
    // 创建 PCB
    PCB* new_pcb = create_pcb(pid, size);
    new_pcb->next = pcb_list;
    pcb_list = new_pcb;
    return 0;
}

// 释放内存
int free_pcb(int pid) {
    PCB* p = find_pcb(pid);
    if(p == NULL)
        return -1;
    FREE_NODE* free_block = (FREE_NODE*)malloc(sizeof(FREE_NODE));
    free_block->start_addr = p->memory_size;
    free_block->end_addr = p->memory_size+p->memory_size-1;
    p->memory_size = 0;
    if(pcb_list == p)
        pcb_list = pcb_list->next;
    else {
        PCB* pre_pcb = pcb_list;
        while(pre_pcb->next != p)
            pre_pcb = pre_pcb->next;
        pre_pcb->next = p->next;
    }
    // 释放内存
    if(free_list == NULL) {     // 空闲链表为空
        free_block->next = NULL;
        free_list = free_block;
    } else {
        FREE_NODE* pre_free_node = NULL;
        FREE_NODE* cur_free_node = free_list;
        while(cur_free_node != NULL && cur_free_node->start_addr <= free_block->start_addr) {
            pre_free_node = cur_free_node;
            cur_free_node = cur_free_node->next;
        }
        // 按块首地址升序插入空闲链表
        if(pre_free_node == NULL) { // 更新头结点
            if(free_block->end_addr+1 == free_list->start_addr) {
                free_list->start_addr = free_block->start_addr;
                free_block = free_list;
            } else
                free_block->next = free_list;
            free_list = free_block;
        } else if(pre_free_node->end_addr+1 == free_block->start_addr && cur_free_node != NULL && cur_free_node->start_addr == free_block->end_addr+1) { // 与两侧空闲块合并
            pre_free_node->end_addr = cur_free_node->end_addr;
            pre_free_node->next = cur_free_node->next;
            free(cur_free_node);
            if(free_block->start_addr == pre_free_node->end_addr+1) {
                pre_free_node->end_addr = free_block->end_addr;
                free(cur_free_node);
            } else {
                free_block->next = pre_free_node;
                pre_free_node->next = cur_free_node;
            }
            free(free_block);
        } else if(pre_free_node->end_addr+1 == free_block->start_addr) { // 与前面的空闲块合并
            pre_free_node->end_addr = free_block->end_addr;
            free_block->next = pre_free_node->next;
            pre_free_node->next = free_block;
        } else if(cur_free_node != NULL && cur_free_node->start_addr == free_block->end_addr+1) { // 与后面的空闲块合并
            cur_free_node->start_addr = free_block->start_addr;
            free_block->next = cur_free_node;
            pre_free_node->next = free_block;
        } else {    // 插入到空闲链表中
            free_block->next = cur_free_node;
            pre_free_node->next = free_block;
        }
    }
    return 0;
}

// 打印内存使用情况
void print_memory_status() {
    FREE_NODE* p = free_list;
    if(p == NULL) {
        printf("内存已全部分配\n");
        return;
    }
    printf("空闲内存:\n");
    while(p != NULL) {
        printf("起始地址:%d,结束地址:%d,空闲大小:%dKB\n", p->start_addr, p->end_addr, (p->end_addr-p->start_addr+1)/1024);
        p = p->next;
    }
    printf("已分配内存:\n");
    PCB* q = pcb_list;
    while(q != NULL) {
        printf("进程 ID:%d,占用内存大小:%dKB\n", q->pid, q->memory_size/1024);
        q = q->next;
    }
}

int main() {
    init_free_linklist();   // 初始化空闲链表
    malloc_pcb(1, 2048);    // 为进程 1 分配 2KB 的内存
    malloc_pcb(2, 4096);    // 为进程 2 分配 4KB 的内存
    malloc_pcb(3, 8192);    // 为进程 3 分配 8KB 的内存
    free_pcb(2);            // 释放进程 2 的内存
    print_memory_status();  // 打印内存使用情况
    return 0;
}
总结

最差适合算法在内存管理中广泛应用,因为它能够及时释放不再使用的内存,从而使可用内存更加充足,提高系统的效率。该算法对于内存的释放和分配十分灵活,但同时也存在一定的缺陷,比如容易出现内存碎片等问题。因此,在实际使用中,需要根据具体情况进行选择和改进,以达到最优的内存管理效果。