1 / 22

数据结构与算法 Data Structure Algorithms 烟台南山学院信息科技学院 数据结构与算法教学组

数据结构与算法 Data Structure Algorithms 烟台南山学院信息科技学院 数据结构与算法教学组. 内存的初始状态. U 1. U 2. U 3. U 4. 系统运行初期. 系统运行若干时后. U 2. U 4. 动态存储管理概述. 存储原理 计算机内存在刚开始工作时,空闲部分是一个整块的连续区域; 随着用户进入系统,多次申请和释放内存以后,空闲部分不再是连续的了,而成了多个空闲区。常用链表管理,即可利用空间表 动态存储管理 指系统随机地根据用户程序申请空间的大小,进行分配空间和回收不用空间所进行的内存管理。. 0. 0. 0.

cian
Download Presentation

数据结构与算法 Data Structure Algorithms 烟台南山学院信息科技学院 数据结构与算法教学组

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 数据结构与算法Data Structure Algorithms 烟台南山学院信息科技学院 数据结构与算法教学组

  2. 内存的初始状态 U1 U2 U3 U4 系统运行初期 系统运行若干时后 U2 U4 动态存储管理概述 • 存储原理 • 计算机内存在刚开始工作时,空闲部分是一个整块的连续区域; • 随着用户进入系统,多次申请和释放内存以后,空闲部分不再是连续的了,而成了多个空闲区。常用链表管理,即可利用空间表 • 动态存储管理 • 指系统随机地根据用户程序申请空间的大小,进行分配空间和回收不用空间所进行的内存管理。

  3. ... 0 0 0 200 300 150 av tag space size link tag=0:空闲 tag=1:使用 可利用空间表及分配方法 • 可利用空间表 • 将所有内存空闲块用链表连接而成; • 空闲块的大小可以是全相同的,也可以是分成若干固定大小的,还可以是随机大小的。

  4. 分配方法 • 首次拟合法 • 分配找到的第一个不小于n的空闲块的一部分。 • 操作方便,查找快捷; • 最佳拟合法 • 分配不小于n且最接近n的空闲块的一部分。 • 尽可能将大的空闲块留给大程序使用; • 最坏拟合法 • 分配不小于n且是最大的空闲块的一部分。 • 尽可能减少分配后无用碎片;

  5. 内存的分配与回收 • 分配 • 根据申请内存大小利用相应的分配策略分配给用户所需的空间; • 若分配块大小与申请大小相差不多,则将此块全部分给用户; • 否则,就需将分配块分为两部分,一部分给用户使用,另一部分继续留在可利用空间表中。 • 回收 • 测试回收块前后相邻内存块是否空闲; • 若是则需将回收块与相邻空闲块合并成较大的空闲块,再链入可利用空间表中。

  6. 8.3 边界标识法 • 用以进行动态分区分配的一种管理方法 • 可利用空间表的结点结构

  7. 边界标识法的数据结构 struct BLK { struct BLK *llink; #define ulink llink //ulink直接利用llink域 int tag; int size; /* 不包括头和脚占用的空间,必须是sizeof(struct BLK)的倍数 */ struct BLK *rlink; }; #define FootLoc(p) \ (struct BLK *)((char *)p + sizeof(struct BLK) + p->size)

  8. 分配算法 • 将所有的空闲块链接在一个双重循环链表结构的可利用空间表中; • 分配可按首次拟合法或最佳拟合法进行; • 为避免过多碎片,设一常量EPSILON • m-n  EPSILON将大小为m的块全部分出 • > EPSILON分出n大小,剩余留下

  9. 分配算法描述 void *mem_alloc(int nbytes) { #define u sizeof(struct BLK); 修正nbytes = (nbytes + u -1) / u * u; /*u为2n有:nbytes = (nbytes+u-1)&~(u-1) */ 从链表中找满足size>=nbytes的块p; if (p==NULL) return NULL; if (p->size – nbytes <= EPSILON) { p脱离空闲链; p->tag = FootLoc(p)->tag = 1; return p+1; } else { p->size -= nbytes + 2 * sizeof(struct BLK); f = FootLoc(p); f->tag = 0; f->uplink = p; p = f + 1; p->tag = 1; p->size = nbytes; f = FootLoc(p); f->tag = 1; f->uplink = p; return p+1; } }

  10. 回收算法 • 根据回收缓冲区地址,找到当前内存块的管理信息 p = (struct BLK *)buf – 1; • 与此内存块紧邻的,处于高地址端的内存块的管理信息 h = (struct BLK *)((char *)(p+2) + p->size); • 与此内存块紧邻的,处于低地址端的内存块的管理信息 l = (p-1)->uplink; • 判l->tag和h->tag,知低端/高端内存块是否空闲,决定是否和低端/高端空闲块合并

  11. 回收算法描述 void mem_free(void *buf) { p = (struct BLK *)buf – 1; p->tag = FootLoc(p)->tag = 0; h = (struct BLK *)((char *)(p+2) + p->size); if (h->tag == 0) { h脱离空闲块链表; FootLoc(h)->uplink = p; p->size += h->size + 2 * sizeof(struct BLK); } l = (p-1)->uplink; if (l->tag) { 将p加入到空闲块链表; } else { l->size += p->size + 2 * sizeof(struct BLK); FootLoc(p)->uplink = l; } } (上述算法未考虑p为可分配空间第一块和最后一块的特殊情况)

  12. 边界表示法的问题 • 查找适合需要的块,需要较多的时间 • 查找适合需要的块的策略(最先/最佳/最坏),每种都有缺陷 • 碎片问题

  13. 8.4 伙伴系统 • 伙伴系统的空闲块大小以2k (k=n, n+1,n+2,…,m)标定。按k值不同组织成多个空闲块链表av[]。设n=5,最小分配32字节,用一张位图维护内存中每个32字节块的使用情况(1:已分配,0:空闲) • 系统开始时只有一个空闲块,大小为2m • 分配(访问链表av[k]) • 将满足用户需求的2k大小的空闲块分配给用户 • av[k]链表空,就找2k+1的空闲块,将其分为两半(互称伙伴),一半给用户,另一半加入av[k]链表中 • 回收: • 只有伙伴才合并,并将合并后的新空闲块加入上一级大小的空闲块链表中。

  14. { Z+2k当 Z mod 2k+1 = 0 Buddy(k,Z)= Z - 2k当 Z mod 2k+1 = 2k 伙伴系统(续) • 首地址为Z,大小为2k的内存块,其伙伴为 例:大小128字节,首地址为0xE580的内存块,其伙伴为0xE500 例:大小128字节,首地址为0xF600的内存块,其伙伴为0xF680

  15. 分配和回收算法 • 分配算法 当用户申请大小为n的内存请求,在可利用空间表上寻找结点大小与n相匹配的表 • 表非空,分配表中第一个内存块 • 表空,从更大的非空表中查找,直到找到一个空闲块,切割出所需要大小的块 • 未分配部分,插入到相应的空闲表中 • 回收算法 判断伙伴是否为空闲块(回收算法需了解释放的块大小) • 否,将释放的空闲块插入到相应表中; • 是,找到伙伴,伙伴出队,合并 • 合并后,判断合并后的块的伙伴是否是空闲块,如果是,继续合并成更大的块。依次重复,直到归并后的块的伙伴不空闲。再插入到相应的空闲块表中。

  16. 举例:阶段1 分配256,128,64之后,分别是B,C,D

  17. 举例:阶段2 申请128(块F),释放128(块C)

  18. 举例:阶段3 释放64(块D)

  19. 伙伴系统的数据结构 struct BLK { int kval; struct BLK *prev, *next; }; struct BLK *av[M]; // 多个空闲链表 应当使用双向循环链表结构

  20. Buddy算法分析 • 可以立即找到空闲块 • 避免了碎片问题 • 申请内存总是以2n字节满足要求,块内浪费 例如:申请130字节,会分得256字节;申请1514字节,会分得2048字节 • 申请/释放可能会导致连锁切块/合并,影响系统效率 例如:当前只有一块空闲,块大小1M, 申请40字节,会导致12次切块,用完立即归还,导致12次合并。如果程序循环式申请40字节,然后归还内存,会导致系统频繁忙碌。

  21. 其它算法 • Lazy-Buddy 解决申请/释放可能会导致连锁切块/合并。该合并时,通过一定“lazy”策略,暂时不合并,在合适的时机合并 • Slab 最早出现在Solaris, 在Linux中采用 避免了碎片问题,并且与内存的分页系统很好配合工作,分配归还的效率很高。 基本思路:每次申请一个内存页面(4096字节)或者多个,切割成所需要的固定大小。不同大小的内存申请,使用不同的空闲队列。

  22. 作业 • 边界标识法需要哪些管理信息?给出相应的数据结构定义。在回收用户指定的缓冲区buf时,如何判断紧邻该缓冲区的上端内存和下端内存是否空闲?给出回收算法。 • 使用伙伴算法管理地址从0开始的16M字节内存,内存分配的最小单位为128字节。系统释放内存地址为十六进制BBCC00的1024字节内存: (1) 如何确定这一待释放内存块的伙伴的地址?地址值是多少? (2) 如何判断它的伙伴能否与它合并

More Related