4.23实验二:存储管理动态分区分配及回收算法

实验二:存储管理动态分区分配及回收算法

一、实验目的

分区管理是应用较广泛的一种存储管理技术。本实验要求用一种结构化高级语言构造分区描述器,编制动态分区分配算法和回收算法模拟程序,并讨论不同分配算法的特点。

二、实验要求

1、编写: First Fit Algorithm

2、编写:Best Fit Algorithm

3、编写:空闲区回收算法

提示和说明:

(一)主程序

1、定义分区描述器 node,包括 3个元素:

(1)adr--分区首地址

(2)size--分区大小

(3)next--指向下一个分区的指针

2、定义 3个指向 node 结构的指针变量:

(1)head1--空闲区队列首指针

(2)back1--指向释放区 node 结构的指针

(3)assign--指向申请的内存分区 node 结构的指针

3、定义1个整形变量:

fee--用户申请存储区的大小(由用户键入)

(二)过程

1、定义 check 过程,用于检查指定的释放块(由用户键入)的合法性

2、定义assignmentl 过程,实现 First Fit Algorithm

3、定义assignment2 过程,实现 Best Fit Algorithm

4、定义 acceptment1 过程,实现 First Fit Algorithm 的回收算法

5、定义 acceptment2 过程,实现 Best FitAlgorithm 的回收算法

6、定义print过程,打印空闲区队列

(三)执行

程序首先申请一整块空闲区,其首址为0,大小为32767:然后,提示用户使用哪种分配算法,再提示是分配还是回收;分配时要求输入申请区的大小,回收时要求输入释放区的首址和大小。

(四)输出

要求每执行一次,输出一次空闲区队列情况,内容包括:编号,首址,终址,大小

:输出空闲区队列的排序,应符合所用分配算法的要求

三、实验过程

1.准备

A. 查阅相关资料:

习动态分区分配算法原理(首次适应算法、最佳适应算法)

了解内存回收时的四种情况(上邻、下邻、上下邻、不邻)

研究链表数据结构在内存管理中的应用

B. 初步编写程序:

C. 准备测试数据:

设计多种分配和回收场景

包括正常情况和边界情况测试用例

2.上机调试

测试首次适应算法

​测试最佳适应算法​

​边界条件测试​

3. 主要流程和源代码

    #include <stdio.h>

#include <stdlib.h>

#include <limits.h>

 

// 分区描述器结构

typedef struct node {

    int adr;            // 分区首地址

    int size;           // 分区大小

    struct node *next;  // 指向下一个分区的指针

} Node;

 

// 函数声明

void assignment1(Node *head, int fee);      // 首次适应分配算法

void assignment2(Node *head, int fee);      // 最佳适应分配算法

void acceptment1(Node *head, int adr, int size); // 首次适应回收算法

void acceptment2(Node *head, int adr, int size); // 最佳适应回收算法

void print(Node *head);                     // 打印空闲区队列

int check(Node *head, int adr, int size);   // 检查释放块合法性

 

int main() {

    // 初始化空闲区队列

    Node *head1 = (Node*)malloc(sizeof(Node));  // 头节点

    Node *init = (Node*)malloc(sizeof(Node));   // 初始空闲区

    

    init->adr = 0;

    init->size = 32767;

    init->next = NULL;

    head1->next = init;

    

    int algorithm, operation, fee, adr, size;

    

    printf("========== 动态分区管理模拟程序 ==========\n");

    

    while(1) {

        printf("\n选择分配算法: 1-首次适应 2-最佳适应 3-退出\n");

        scanf("%d", &algorithm);

        

        if(algorithm == 3) break;

        if(algorithm != 1 && algorithm != 2) {

            printf("无效选择!\n");

            continue;

        }

        

        printf("选择操作: 1-分配 2-回收\n");

        scanf("%d", &operation);

        

        if(operation == 1) {

            printf("输入申请内存大小: ");

            scanf("%d", &fee);

            if(fee <= 0) {

                printf("申请大小必须为正数!\n");

                continue;

            }

            

            if(algorithm == 1)

                assignment1(head1, fee);  // 首次适应

            else

                assignment2(head1, fee);  // 最佳适应

        }

        else if(operation == 2) {

            printf("输入释放区首址和大小: ");

            scanf("%d %d", &adr, &size);

            if(size <= 0) {

                printf("释放大小必须为正数!\n");

                continue;

            }

            

            if(!check(head1, adr, size)) {

                printf("释放区不合法!\n");

                continue;

            }

            

            if(algorithm == 1)

                acceptment1(head1, adr, size);

            else

                acceptment2(head1, adr, size);

        }

        else {

            printf("无效操作!\n");

            continue;

        }

        

        print(head1);  // 打印空闲区队列

    }

    

    // 释放内存

    Node *p = head1->next;

    while(p != NULL) {

        Node *temp = p;

        p = p->next;

        free(temp);

    }

    free(head1);

    

    return 0;

}

 

// 首次适应分配算法

void assignment1(Node *head, int fee) {

    Node *p, *q;

    q = head;

    p = head->next;

    

    while(p != NULL) {

        if(p->size >= fee) {  // 找到第一个足够大的空闲区

            if(p->size == fee) {  // 刚好满足

                q->next = p->next;

                printf("分配成功! 首址: %d 大小: %d\n", p->adr, fee);

                free(p);

            } else {  // 分割空闲区

                Node *alloc = (Node*)malloc(sizeof(Node));

                alloc->adr = p->adr;

                alloc->size = fee;

                p->adr += fee;

                p->size -= fee;

                printf("分配成功! 首址: %d 大小: %d\n", alloc->adr, fee);

                free(alloc);  // 实际分配不需要保存,这里只是模拟

            }

            return;

        }

        q = p;

        p = p->next;

    }

    printf("无足够大的空闲区!\n");

}

 

// 最佳适应分配算法

void assignment2(Node *head, int fee) {

    Node *p, *q, *best, *best_prev;

    int min_size = INT_MAX;

    

    q = head;

    p = head->next;

    best = NULL;

    best_prev = NULL;

    

    while(p != NULL) {

        if(p->size >= fee && p->size < min_size) {

            min_size = p->size;

            best = p;

            best_prev = q;

        }

        q = p;

        p = p->next;

    }

    

    if(best != NULL) {

        if(best->size == fee) {  // 刚好满足

            best_prev->next = best->next;

            printf("分配成功! 首址: %d 大小: %d\n", best->adr, fee);

            free(best);

        } else {  // 分割空闲区

            Node *alloc = (Node*)malloc(sizeof(Node));

            alloc->adr = best->adr;

            alloc->size = fee;

            best->adr += fee;

            best->size -= fee;

            printf("分配成功! 首址: %d 大小: %d\n", alloc->adr, fee);

            free(alloc);  // 实际分配不需要保存,这里只是模拟

        }

    } else {

        printf("无足够大的空闲区!\n");

    }

}

 

// 首次适应回收算法

void acceptment1(Node *head, int adr, int size) {

    Node *p, *q, *new_node;

    int end = adr + size;

    

    q = head;

    p = head->next;

    

    while(p != NULL && p->adr < end) {

        q = p;

        p = p->next;

    }

    

    // 检查是否与前面的空闲区相邻

    if(q != head && (q->adr + q->size) == adr) {

        q->size += size;

        // 检查是否与后面的空闲区相邻

        if(p != NULL && (adr + size) == p->adr) {

            q->size += p->size;

            q->next = p->next;

            free(p);

        }

    }

    // 检查是否与后面的空闲区相邻

    else if(p != NULL && end == p->adr) {

        p->adr = adr;

        p->size += size;

    }

    // 不与任何空闲区相邻,创建新节点

    else {

        new_node = (Node*)malloc(sizeof(Node));

        new_node->adr = adr;

        new_node->size = size;

        new_node->next = p;

        q->next = new_node;

    }

    

    printf("回收成功! 首址: %d 大小: %d\n", adr, size);

}

 

// 最佳适应回收算法(与首次适应回收算法相同,因为回收逻辑不依赖分配策略)

void acceptment2(Node *head, int adr, int size) {

    acceptment1(head, adr, size);

}

 

// 打印空闲区队列

void print(Node *head) {

    Node *p = head->next;

    int i = 1;

    

    printf("\n空闲区队列:\n");

    printf("编号\t首址\t终址\t大小\n");

    

    while(p != NULL) {

        printf("%d\t%d\t%d\t%d\n", i, p->adr, p->adr + p->size - 1, p->size);

        p = p->next;

        i++;

    }

}

 

// 检查释放块合法性(简化版,实际应检查是否与已分配区重叠)

int check(Node *head, int adr, int size) {

    // 检查释放区是否在合法范围内

    if(adr < 0 || adr + size > 32767) {

        return 0;

    }

    

    // 检查释放区是否与空闲区重叠(简化检查)

    Node *p = head->next;

    while(p != NULL) {

        if((adr >= p->adr && adr < p->adr + p->size) ||

           (adr + size > p->adr && adr + size <= p->adr + p->size)) {

            return 0;

        }

        p = p->next;

    }

    

    return 1;

}

4.遇到的主要问题和解决方法

A. :回收时未检查释放区是否与已分配区重叠(代码中仅检查与空闲区重叠)。

​  解决方法​:需要维护已分配区列表或在空闲区检查时更严格(当前简化实现可能不完善)。

四、实验结果

 

 

 

五、实验总结

通过本次实验,我学到了动态分区管理的基本原理和实现方法,首次适应算法和最佳适应算法的特点和差异,内存回收时的合并策略,使用链表数据结构管理内存空间的方法,提高了编程能力和调试技巧。

posted @ 2025-05-19 08:43    阅读(33)  评论(0)    收藏  举报