动态异长分区内存分配与去配算法的设计-最佳适应算法

这篇具有很好参考价值的文章主要介绍了动态异长分区内存分配与去配算法的设计-最佳适应算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.1  设计目的

理解存储管理的功能,掌握动态异长分区内存管理中的最佳适应算法。

1.2  设计要求

本设计要求模拟最佳适应算法的分配算法和回收算法。

1.3  数据结构设计

空闲区域首址

空闲区域长度

addr

size

图1-1 空闲区域表

为了实现存储资源的分配和回收,操作系统需要记录内存资源使用情况,即哪些区域尚未分配,哪些区域已经分配以及分配给哪些进程等。为此一般需要两个表,一个为分配表, 另外一个为空闲区域表。前者记录已经分配的区域, 后者记录着所有当前未被进程占用的空闲区域, 如图1-1所示。

显然, 没有记录于表中的区域即为已被进程所占用的非空闲区域,在实际的操作系统中,这些区域登记在进程的PCB中。而PCB中除了关于内存资源的信息外,还有其它大量信息。

由于本设计是对存储管理算法的模拟,所以用一个线程来代表一个进程,用线程驻留区域表来描述线程占用的内存空间,如图1-2所示。

线程名称

驻留区始址

驻留区大小

a

0

15

b

20

10

……

……

……

图1-2 线程驻留区表

同时,需要一张表来记录各个线程对内存的请求信息,如图1-3所示。

线程名称

请求大小(KB)

预计驻留时间( 秒)

thread_1

15

8

thread_2

11

4

……

……

……

图1-3 内存申请表

1.4  算法设计

1.4.1  算法结构设计

分配时取满足申请要求且长度最小的空闲区域。在实现时, 可将系统中所有的空闲区域按照长度由小到大的次序依次记录于空闲区域表中。与最先适应算法相类似, 当进程申请存储空间时, 系统由表的头部开始查找, 取第一个满足要求的表目。如果该表目所对应的区域长度恰好与所申请的区域长度相同, 则将该区域全部分配给申请者。否则将该区域分割为两部分, 一部分的长度与所申请的长度相同, 将其分配给申请者;另一部分即剩余部分的长度为原长度与分配长度之差, 由于剩余部分的长度已经改变,所以应重新将其按长度从小到大的顺序插入到空闲区域表中。

回收时,不仅要按回收区的首地址查询空闲区表,找到与回收区相临的空闲区,将其合并到相临区中,而且要把合并后的回收区按照长度递增的顺序插入到空闲区域表的适当位置。

1.4.2  设计并分析测试数据

假设初始内存布局如图1-4,图中的起始地址以及大小都以KB来衡量。

起始地址

0

15

20

30

40

70

85

105

135

180

占用者

a

b

c

d

e

大  小

15

5

10

10

30

15

20

30

45

20

图1-4初始内存布局

由图1-4可见,初始时共有五个线程驻留在内存,它们是a,b,c,d,e,线程驻留区表如图1-5;还有五个空闲区,空闲区域表如图1-6。

假设现在有三个线程提出内存申请,申请情况见图1-7。经过分析我们得到在每种分配算法下这三个线程所申请到的内存情况。图1-8是最佳适应算法分配情况。

线程名称

驻留区始址

驻留区大小

a

0

15

b

20

10

c

40

30

d

85

20

e

135

45

图1-5 线程驻留区表

空闲区首址

空闲区长度

15

5

30

10

70

15

105

30

180

20

图1-6 空闲区域表

线程名称

请求大小(KB)

预计驻留时间( 秒)

thread_1

15

8

thread_2

11

4

thread_3

3

5

图1-7 内存申请表

线程名称

驻留区始址

驻留区大小

a

0

15
b 20 10
40c30 40

30

d 85 20
e 135 45
thread_1 70 15
thread_2 70 11
thread_3 15 3
图1-8 最佳适应算法线程驻留区表

1.4.3  程序设计

程序包含两个文件,一个是头文件variable_partition.h,另一个是源程序文件variable_partition.cpp。在头文件中定义了宏、数据结构、全局变量、函数声明,源程序中含有各个函数的实现。

在头文件中,结构体FREEAREA、REQUIRE_MEMORY、THREAD_RESIDENCE_MEMORY分别对应于图1-1、图1-2、图1-3中的一行,不同之处是为了构成链表在三个结构体中都有前向指针。数组init_free_area_table对应于图1-6,数组init_thread_require_memory_table对应于图1-5,数组init_thread_residence_memory_table对应于图1-7,为了实现动态分配与释放,用链表重新组织空闲区域表、线程驻留区表和内存申请表,全局变量p_free_area_list是空闲区链首,p_thread_require_memory_queue是内存申请队列的队首,p_thread_residence_memory_list是线程驻留区链首,tail_thread_residence_memory_list是线程驻留区链尾,由于线程驻留区链表被内存分配函数和内存释放函数共享,故用临界区变量CS_THREAD_MEMORY_LIST来保护,同理,屏幕是所有线程共享的,所以用临界区变量CS_SCREEN来保护,空闲区链表被内存分配函数和内存释放函数共享,故用临界区变量CS_FREEAREA_LIST来保护。h_thread是线程句柄数组,用来存放各个线程的句柄。

程序共包含13个函数,按照作用可以将它们分成五组。

第一组包括函数print_space()和函数display_thread_residence_memory(),前者用来显示若干个空格,后者用来显示线程驻留区表;

第二组共十一个函数,用来实现最佳适应分配法,它们的名称及功能如图1-9。

函数名称

函数功能

BF_initialize_freearea_list

初始化空闲区链表:按长度递增排序

BF_delete_freearea_list

删除空闲区链表

BF_initialize_require_memory_list

初始化内存申请链表

BF_delete_require_memory_list

删除内存申请链表

BF_initialize_thread_residence_memory_list

初始化线程驻留区链表

BF_delete_thread_residence_memory_list

删除线程驻留区链表

BF_thread

线程函数:申请内存;驻留内存;释放内存

BF_require_memory

申请一段内存,成功时返回起始地址,失败时返回空

BF_release_memory

释放一段内存

BF_insert_freearea

将空闲区按大小递增的次序插入到空闲区链表中

BF()

初始化函数:创建线程并等待它们结束

图1-9   最佳适应分配法的函数及其功能

1.4.4  程序流程图设计

1.函数关系调用图

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

图1-10   函数关系调用图

2.主要程序流程图

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

图1-11   主要程序流程图

3.内存申请函数流程图

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

图1-12  内存申请函数流程图

4.内存释放函数流程图

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

图1-13  内存释放函数流程图

1.5  程序代码

内存申请函数

// 最佳适应分配算法的内存申请函数
int BF_require_memory(int size) {
    FREEAREA *p = p_free_area_list;
    FREEAREA *prev = NULL;
    int best_fit_start = -1;
    int best_fit_size = INT_MAX;
    // 寻找最佳适应的空闲区
    while (p != NULL) {
        if (p->size >= size && p->size < best_fit_size) {
            best_fit_start = p->start_address;
            best_fit_size = p->size;
            prev = p;
        }
        p = p->next;
    }
    // 如果找到了最佳适应的空闲区
    if (best_fit_start != -1) {
        // 划分空闲区
        if (best_fit_size > size) {
            FREEAREA *new_free_area = (FREEAREA *)malloc(sizeof(FREEAREA));
            new_free_area->next = prev->next;
            new_free_area->start_address = best_fit_start + size;
            new_free_area->size = best_fit_size - size;

            prev->next = new_free_area;
        }
        // 从空闲区链表中删除已分配的空闲区
        if (prev == NULL) {
            p_free_area_list = p_free_area_list->next;
        } else {
            prev->next = prev->next->next;
        }
        return best_fit_start;
    }
    return -1; // 内存申请失败
}

内存释放函数

// 最佳适应分配算法的内存释放函数
void BF_release_memory(int start_address,int size){
EnterCriticalSection(&CS_FREEAREA_LIST);
    FREEAREA *temp, *p, *pp;
    p=p_free_area_list;
    temp = new FREEAREA;
    temp->start_address=start_address;
    temp->size=size;
    temp->next=NULL;
    int flag=0;
    while(1) {
  if(p->next!=NULL&&start_address+size<=p->next->start_address&&start_address>=p->start_address+p->size) {
            temp->next=p->next;
            p->next=temp;
            flag=1;
        }
        if(flag==1||p->next==NULL) break;
        p=p->next;
    }
    if(start_address>=p->start_address+p->size) {
        if(flag==0)
            p->next=temp;
    } else {
        if(flag==0) {
            pp=p_free_area_list;
            temp->next=pp;
            pp->next=p_free_area_list->next;
            p_free_area_list=temp;
        }
    }
    FREEAREA *ppp;
    ppp=p_free_area_list;
    while(1) {
        if(ppp->next!=NULL) {
            if(ppp->start_address+ppp->size==ppp->next->start_address) {
                ppp->size+= ppp->next->size;
                if(ppp->next->next!=NULL)
                    ppp->next=ppp->next->next;
                else {
                    ppp->next=NULL;
                }
                continue;
            }
        }
        if(ppp->next!=NULL) ppp=ppp->next;
        else break;
    }
    EnterCriticalSection(&CS_SCREEN);
    THREAD_RESIDENCE_MEMORY *q;
    q = p_thread_residence_memory_list;
    if (q->start_address == start_address) {
        p_thread_residence_memory_list = p_thread_residence_memory_list->next;
    } else {
        while (q->next != NULL) {
            if (q->next->start_address == start_address) {
                if (q->next == tail_thread_residence_memory_list) {
                    tail_thread_residence_memory_list = q;}
                q->next = q->next->next;
                break;
}
            q = q->next;
}
}
    LeaveCriticalSection(&CS_SCREEN);
    LeaveCriticalSection(&CS_FREEAREA_LIST);
}

1.6  运行结果

1.6.1  运行结果截图

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

图1-14  运行结果一

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

动态异长分区内存分配与去配算法的设计-最佳适应算法,算法

图1-15  运行结果二

1.6.2  运行结果分析

第一次运行:

线程thread_1:

请求内存成功,分配了大小为15 KB的内存,起始地址为70 KB。

显示线程内存驻留区链表。

线程thread_2:

请求内存成功,分配了大小为11 KB的内存,起始地址为70 KB。

显示线程内存驻留区链表。

线程thread_3:

请求内存成功,分配了大小为3 KB的内存,起始地址为15 KB。

显示线程内存驻留区链表。

模拟结束后:

所有线程执行完毕后,显示线程内存驻留区链表。

第二次运行:

线程thread_2:

请求内存成功,分配了大小为11 KB的内存,起始地址为70 KB。

显示线程内存驻留区链表。

线程thread_3:

请求内存成功,分配了大小为3 KB的内存,起始地址为15 KB。

显示线程内存驻留区链表。

线程thread_1:

请求内存成功,分配了大小为15 KB的内存,起始地址为70 KB。

显示线程内存驻留区链表。

模拟结束后:

所有线程执行完毕后,显示线程内存驻留区链表。

对于两次运行结果不同做以下原因分析:

每次运行结果不同的原因主要是因为程序中使用了多线程,多线程程序的执行顺序是不确定的。在多线程环境中,操作系统的调度器决定了每个线程何时获得 CPU 时间。不同运行中线程的交替执行顺序可能不同,从而导致不同的结果。

程序实现了一个使用线程的内存分配和释放算法--最佳适应算法。线程被创建来模拟不同的进程,这些进程或任务请求和释放内存。线程的并发执行,加上潜在的竞争条件和线程争用,可能导致每次运行中内存分配和释放的顺序不同。

1.7  设计总结

        在设计最佳适应算法的动态异长分区内存管理系统时,理解了存储管理的关键功能,并掌握了最佳适应算法的分配和回收过程。在数据结构设计方面,建立了两张关键表:分配表和空闲区域表。分配表记录已经分配的内存区域,而空闲区域表则记录当前未被进程占用的空闲内存区域。通过线程驻留区域表和内存申请表,成功地将进程与其内存请求信息关联起来,以便模拟实际存储管理情境。在算法设计方面,最佳适应算法的核心思想是分配时选择满足要求且长度最小的空闲区域。实现了按照空闲区域长度由小到大的顺序记录空闲区域表,并在分配时从表头开始查找符合条件的区域。若找到匹配的区域,根据申请大小进行分配或分割,并重新排序插入剩余部分。在回收过程中,实现了按照回收区的首地址查询空闲区表,找到相邻的空闲区并合并。然后,将合并后的回收区按长度递增的顺序插入到空闲区域表的适当位置。同时每次运行结果不同的原因主要是因为程序中使用了多线程,多线程程序的执行顺序是不确定的。在多线程环境中,操作系统的调度器决定了每个线程何时获得 CPU 时间。不同运行中线程的交替执行顺序可能不同,从而导致不同的结果,对于操作系统中进程的并发有了更好的理解。文章来源地址https://www.toymoban.com/news/detail-827173.html

到了这里,关于动态异长分区内存分配与去配算法的设计-最佳适应算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 编写C语言程序,模拟实现首次/最佳/最坏适应算法的内存块分配和回收,要求每次分配和回收后显示出空闲分区和已分配分区的情况。假设初始状态下,可用的内存空间为640KB。(江西师范大学软件学院 操作系统)

    为了实现动态分区分配,通常将系统中的空闲分区链接成一个链。所谓顺序查找是指依次搜索空闲分区链上的空闲分区,去寻找一个大小能满足要求的分区。 --------计算机操作系统(第四版) 可变分区也称动态分区,在指作业装入内存时,从可用的内存中划出一块连续的区域

    2024年02月08日
    浏览(43)
  • 操作系统动态内存分配算法【C语言实现】

    题目: 采用五个算法,各自作业在1024kB空间上分配情况。 内存可变分区分配仿真算法 :首次适应,下次适应,最佳适应,最坏适应和快速分配。 使用的结构体数组表示起始地址,内存块大小,内存块状态(0空闲,1占用) void bubbleprint(struct Info info[]) 函数是为了内存块大小

    2024年02月03日
    浏览(43)
  • 操作系统动态分区分配方式C/C++语言(首次适应算法(FF)循环首次适应算法(NF)最best适应算法(BF)最坏适应算法(WF))

    一、动态分区分配算法 为把一个新作业装入内存,须按照一定的分配算法, 从空闲分区表或空闲分区链中出一分区分配给该作业。由于内存分配算法对系统性能有很大的影响,故人们对它进行了较为广泛而深入的研究,于是产生了许多动态分区分配算法。传统的四种分配算

    2024年02月10日
    浏览(41)
  • 资源分配问题【算法设计与分析】<动态规划问题>

    问题分析: ( 要把问题分为多步解决,每步求出子问题的多个最优策略后一步依赖于上一步的最有策略,最后一步得出问题的解) (1)首先要考虑分配给项目A的资金与利润的关系。得到此时投资数x与其相对应的 的关系。 (2)其次要考虑分配给前两个项目A,B的总资金 与利

    2023年04月08日
    浏览(38)
  • 实验名称:动态分区分配方式模拟

    实验名称:动态分区分配方式模拟 实验目的 进一步加深对动态分区分配管理方式的理解;掌握动态分区分配方式使用的数据结构、分配算法和回收算法 实验内容 编写C语言程序,模拟实现首次/最佳/最坏适应算法的内存块分配和回收,要求每次分配和回收后显示出空闲分区和

    2024年02月03日
    浏览(40)
  • 【C/C++】静态内存分配与动态内存分配

    1.1 - 定义概述 内存分配 (Memory Allocation) 是指为计算机程序或服务分配物理内存空间或虚拟内存空间的一个过程。通常在程序执行前或执行时完成内存分配。 1.2 - 分类概述 存在两种类型的内存分配: 编译时内存分配或静态内存分配 (Compile-time or Static Memory Allocation) 运行时内存

    2024年02月11日
    浏览(40)
  • C++——内存分配与动态内存管理

    🌸作者简介: 花想云 ,在读本科生一枚,致力于 C/C++、Linux 学习。 🌸 本文收录于 C++系列 ,本专栏主要内容为 C++ 初阶、C++ 进阶、STL 详解等,专为大学生打造全套 C++ 学习教程,持续更新! 🌸 相关专栏推荐: C语言初阶系列 、 C语言进阶系列 、 数据结构与算法 本章我们

    2023年04月17日
    浏览(54)
  • 动态分配内存与释放

    1.malloc malloc()可以找到一个大小合适的块。 内存是匿名的,也就是说,malloc()分配了内存,但没有为它指定名字。 格式如下: double*ptd; ptd=(double*)malloc(30*sizeof(double)); ps:ptd可以看成是一个数组。 malloc()可能分配不到所需的内存。在这种情况下,该函数返回空指针。

    2024年01月17日
    浏览(61)
  • 用指针实现内存动态分配

    导引 :已知:变量在使用前必须被定义且安排好存储空间。且变量有这么一些分类:全局变量、静态局部变量【它们的储存一般是在编译时确定,在程序开始执行前完成。】自动变量【在执行进入变量定义所在的复合语句时为它们分配存储,变量的大小也是静态确定的。临时

    2023年04月09日
    浏览(79)
  • C++ 指针进阶:动态分配内存

    malloc 是 stdlib.h 库中的函数,原型为 void *__cdecl malloc(size_t _Size); : 作用 : malloc 函数沿空闲链表(位于内存 堆空间 中)申请一块满足需求的内存块,将所需大小的内存块分配给用户剩下的返回到链表上; 并返回指向该内存区的首地址的指针,意该指针的类型为 void * ,因此

    2024年02月05日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包