数据结构课ppt8动态存储管理

合集下载

(2024年)《数据结构》全套课件

(2024年)《数据结构》全套课件

30
树形数据结构的查找算法
二叉排序树的查找
从根节点开始,若查找值小于当前节点 值,则在左子树中查找;若大于当前节 点值,则在右子树中查找。
VS
平衡二叉树的查找
在保持二叉排序树特性的基础上,通过旋 转操作使树保持平衡,提高查找效率。
2024/3/26
31
散列表的查找算法
散列函数的设计
将关键字映射为散列表中位置的函数。
过指针来表示。
链式存储的特点
逻辑上相邻的元素在物理位置上 不一定相邻;每个元素都包含数
据域和指针域。
链式存储的优缺点
优点是插入和删除操作不需要移 动元素,只需修改指针;缺点是
存储密度小、空间利用率低。
2024/3/26
11
线性表的基本操作与实现
插入元素
在线性表的指定位 置插入一个元素。
查找元素
在线性表中查找指 定元素并返回其位 置。
自然语言处理的应用
在自然语言处理中,需要处理大量的文本数据,数据结构中的字符 串、链表、树等可以很好地支持文本的处理和分析。
41
数据结构在计算机网络中的应用
2024/3/26
路由算法的实现
计算机网络中的路由算法需要大量的数据结构支持,如最短路径 树、距离向量等。
网络流量的控制
在计算机网络中,需要对网络流量进行控制和管理,数据结构中的 队列、缓冲区等可以很好地支持流量的控制。
37
06
数据结构的应用与拓展
2024/3/26
38
数据结构在算法设计中的应用
01
作为算法设计的基 础
数据结构为算法提供了基本操作 和存储方式,是算法实现的重要 基础。
02
提高算法效率

cunit动态内存分配与数据结构实用PPT课件

cunit动态内存分配与数据结构实用PPT课件
第6页/共118页
7.1.1自由存储区内存的分配与释放
动态分配数组的特点:
1. 变量n在编译时没有确定的值,而是在运行中输入,按运行 时所需分配空间,这一点是动态分配的优点,可克服数组 “大开小用”的弊端,在表、排序与查找中的算法,若用 动态数组,通用性更佳。delete [ ]pc是将n个字符的空间释 放,而用delete pc则只释放了一个字符的空间;
char *pName; //为了演示深复制,不用string类 public:
student(); //默认构造函数 student(char *pname); //带参数构造函数 student(student &s); //复制构造函数 ~student(); //析构函数 student & operator=(student &s); }; //复制赋值操作符
第12页/共118页
7.1.2自由存储区对象与构造函数
类对象初始化:
new后面类(class)类型可以有参数。这些参数即构造函数的 参数。但对创建数组,则无参数,只能调用默认的构造函数。
【例7.3】演示自由存储区对象分配和释放。
由自由存储区创建对象数组,只能调用默认 的构造函数,不能调用其他任何构造函数。如果 没有默认的构造函数,则不能创建对象数组。
第17页/共118页
7.1.3 浅复制与深复制
思考:
深入地考虑【例7.4】,如果数据域还有很多其他数 据,甚至有好几个是动态建立的C字符串,深复制是不是太 复杂了?如果使用C++标准字符串string作为成员对象(聚 合)是否就不需要考虑深复制了? 的确是这样的,准确地说,string类的内部包含动态建立字 符数组的操作,其复制构造函数是深复制。如果在student 类中使用string类而不是C字符串,就不要再考虑深复制问 题了。也就是说,动态内存分配和深复制应该放在一个适当 的层面上,一个更单纯的类定义中,如string类。在使用中, 把它作为一个成员对象,就像使用string类对象那样。

第8章动态存储管理

第8章动态存储管理

解决方法
• 访问计数器 如果把地址存放在某个地方 计 访问计数器: 如果把地址存放在某个地方,计 数器就增加一。这说明,计数为0, 数器就增加一。这说明,计数为 ,没有其它 存放地址的情况,则可以收回。 存放地址的情况,则可以收回。 • 占用结点做标志。 占用结点做标志。
**8.6 存储紧缩
• 由于系统的可利用空间始终是一个地址连续 的存储块, 的存储块,因此回收时必须将所释放的空闲 块合并到整个堆上去才能重新使用, 块合并到整个堆上去才能重新使用,这就是 存储紧缩”的任务。 “存储紧缩”的任务。 • 跟磁盘空间整理方法很类似。移动,相邻块 跟磁盘空间整理方法很类似。移动, 合并。需要传送数据(移动数据), ),还需要 合并。需要传送数据(移动数据) 边界标识法
• 它属于上一节讨论中的第三种情况。系统将 它属于上一节讨论中的第三种情况。 所有的空闲块链接在一个双重循环链表结构 的可利用空间表中;分配可按首次拟合进行, 的可利用空间表中;分配可按首次拟合进行, 也可按最佳拟合进行。 也可按最佳拟合进行。
8.3.1 可利用空间表的结构
Llink
tag
size
Rlink
空间 uplink tag
可利用空间表的结点结构定义
可利用空间表的结点结构定义
• 可利用空间表设为双重循环链表。head中的 可利用空间表设为双重循环链表。 中的 比LLINK和RLINK分别指向前驱结点和后继 和 分别指向前驱结点和后继 结点。表中不设表头结点,表头指针Pav可以 结点。表中不设表头结点,表头指针 可以 指向表中任一结点, 指向表中任一结点,即任何一个结点都可看 成是链表中的第一个结点;表头指针为空, 成是链表中的第一个结点;表头指针为空, 则表明可利用空间表为空。 则表明可利用空间表为空。FOOT中的 中的 UPLINK域也为指针,它的值即为该空闲块 域也为指针, 域也为指针 的首地址。 的首地址。

数据结构-第8章动态存储管理

数据结构-第8章动态存储管理

head
llink
tag
size
rlink
space
foot uplink tag
2. 分配算法: (采用首次拟合法) 约定(1)余量的处理 (2)PAV的移动 如图8.6所示。P200 算法描述: space allocboundtag(space *pav,int n) for(p=pav;p&&p->size<n &&p->rlink!=pav;p=p->link); if(!p|| p->size<n) return 0 else { f=footloc(p); pav=p->rlink; if(p->size-n<e) if(pav==p) pav=0
8.5 无用单收集 8.6 存储紧缩 略
else { pav->llink=p->link;p->llink->rlink=pav;} p->tag=f->tag=1;} else {f->tag=1; p->size-=n; f=footloc(p); f->tag=0,f->uplink=p; p=f+1; p->tag=1;p->size=n} return p }} 算法8.1
动态存储管理的基本问题:分配与回收 动态存储分配过程:
系统运行初期
系统运行一段时间后
分配处理:(1)从高地址空闲块中进行分配。 (2)在整个内存中找一合适的空闲块。
可利用空间表结构: (1)目录表 (2)链表
起始地址内存大小使用 Nhomakorabea况10,000 31,000 59,000
15,000 8,000 41,000

动态存储管理.ppt

动态存储管理.ppt

else { //p指向找到的空闲块 f = FootLoc (p); //指向底部 pav = p->rlink; //pav指向*p结点的后继结点 if (p->size-n <= e) { //整块分配,不保留<=e的剩余量 if (pav = = p) //可利用空间表变为空表 pav = NULL; else { //在表中删除分配的结点 pav->llink = p->llink; p->llink->rlink = pav; } // else p->tag = f->tag = 1; //修改分配结点的头部和底部标志 } // if
例如,某动态存储管理系统中的用户请求分配2个字、4个字 或8个字的内存块,则系统建立3个结点大小分别为3个字、5个 字或9个字的链表,它们的表头指针分别为av2、av4和av8。如 图8.3所示。
tag type link
value 0 tag = 1 type = 0 1 2 (a) 占用块 结点大小为2个字 结点大小为4个字 结点大小为8个字 结点结构 空闲块
else { //分配该块的后n个字 f->tag = 1; //修改分配块的底部标志 p->size -= n; //置剩余块大小 f = FootLoc (p); //指向剩余块底部 f->tag = 0; f->uplink = p; //设置剩余块底部 p = f + 1; //指向分配块头部 p->tag = 1; p->size = n; //甚至分配块头部 } return p; } // else } // AllocBoundTag (3)例子 例如,图8.5(b)所示可利用空间表在进行分配之后的状态 如图8.5(c)所示。 (ppt15和16页)

C语言中的动态内存PPT教学课件

C语言中的动态内存PPT教学课件
(2)free函数的参数必须是一个由动态内存分 配方法分配的内存块的首地址(使用malloc 函数分配的内存)
2020/12/11
7
动态分配内存特点
• 内存空间大小可以是一个变量,其值在运 行时确定
• 内存空间在运行时分配,在程序结束时收 回;内存的分配由操作系统参与完成
• 动态分配的内存空间在未释放之前均可以 被引用,保证其生命期
动态分配内存概述
• 什么时候需要动态分配内存?
• 实例:顺序对一批文件进行解析,但是不 知道文件的大小,如何建立缓冲区?
2020/12/11
1
malloc函数 malloc函数原型:
void * malloc(size_t n); n是要分配的内存的大小,返回值是分配内 存的块的首地址
例1:使用malloc函数分配一个可以容纳10个 整型元素的内存空间,并将其用作一个整 型数组
2020/12/11
5
free函数
free函数原型: void free(void * p); p是要释放的已分配内存的块的首地址
释放一块动态分配的内存: 例如: int *p; p = (int *)malloc(sizeof(int)); free(p);
2020/12/11
6
(1)free函数同样是一个库函数
2020/12/11
3
关键代码:
struct test * p; p = (struct test *)malloc(sizeof(struct test));
(1)malloc函数是一个库函数,它并不是C语 言中的关键字:
• 需要头文件<stdlib.h>才可以使用该函数 • 并不是所有的平台都可以使用该函数,尤

数据结构——第八章——动态存储管理PPT教学课件

数据结构——第八章——动态存储管理PPT教学课件

◆ 分配时:从链表中找到一个合适的结点加以分配, 然后将该结点删除之;
◆ 回收时:将空闲块插入到链表中。
实际的动态存储管理实施时,具体的分配和释放的
策略取决于结点(空闲块)的结构。
2020/12/10
6
00000H ⋮ 11000H 12004H 13196H 13740H 160EFH
216EFH
8.2.2 结点结构方式与分配策略
1 请求分配的块大小相同
将进行动态存储分配的整个内存区域(堆)按所需大小 分割成若干大小相同的块,然后用指针链接成一个可利 用空间表。
◆ 分配时:从表的首结点分配,然后删除该结点;
◆ 回收时:将释放的空闲块插入表头。
2 请求分配的块大小只有几种规格
根据统计概率事先对动态分配的堆建立若干个可利
起始地址 空闲块大小 使用情况
12004H 13740H 216EFH
4498 10671 69632
空闲 空闲 空闲
(b) 目录表方式
av
0 4498
0 10671
0 69632 ⋀
326EFH
(a) 堆的状态
(c) 链表方式
图8-2 动态存储管理过程中的内存状态和空闲表结构
2020/12/10
7
2020/12/10
⋮ 11000H 12004H
A 12196H B 12240H
C 130EFH

图8-1 堆的状态
4
8.2 可利用空间表及分配方法
可利用空间表中包含所有可分配的空闲块,当用户 请求分配时,系统从可利用空间表中删除一个结点分配 之;当用户释放其所占内存时,系统即回收并将它插入 到可利用空间表中。因此,可利用空间表亦称做“存储 池”。

第八章 动态存储管理

第八章 动态存储管理

第八章动态存储管理8.11typedef struct {char *start;int size;} fmblock; //空闲块类型char *Malloc_Fdlf(int n)//遵循最后分配者最先释放规则的内存分配算法{while(Gettop(S,b)&&b.size<n){Pop(S,b);Push(T,b); //从栈顶逐个取出空闲块进行比较}if(StackEmpty(S)) return NULL; //没有大小足够的空闲块Pop(S,b);b.size-=n;if(b.size) Push(S,{b.start+n,b.size});//分割空闲块while(!StackEmpty(T)){Pop(T,a);Push(S,a);} //恢复原来次序return b.start;}//Malloc_Fdlfmem_init()//初始化过程{...InitStack(S);InitStack(T); //S和T的元素都是fmblock类型Push(S,{MemStart,MemLen}); //一开始,栈中只有一个内存整块...}//main8.12void Free_Fdlf(char *addr,int n)//与上一题对应的释放算法{while(Gettop(S,b)&&b.start<addr){Pop(S,b);Push(T,b);} //在按地址排序的栈中找到合适的插入位置if(Gettop(T,b)&&(b.start+b.size==addr)) //可以与上邻块合并{Pop(T,b);addr=b.start;n+=b.size;}if(Gettop(S,b)&&(addr+n==b.start)) //可以与下邻块合并{Pop(S,b);n+=b.size;}Push(S,{addr,n}); //插入到空闲块栈中while(!StackEmpty(T)){Pop(T,b);Push(S,b);} //恢复原来次序}//Free_Fdlf8.13void Free_BT(Space &pav,Space p)//在边界标识法的动态存储管理系统中回收空闲块p{n=p->size;f=p+n-1; //f指向空闲块底部if((p-1)->tag&&(f+1)->tag) //回收块上下邻块均为占用块{p->tag=0;f->tag=0;f->uplink=p;if(!pav){p->llink=p;p->rlink=p;}else{q=pav->llink;p->llink=q;p->rlink=pav;q->rlink=p;pav->llink=p;}pav=p;}//ifelse if(!(p-1)->tag&&(f+1)->tag) //上邻块为空闲块{q=(p-1)->uplink;q->size+=n;f->uplink=q;f->tag=0;}else if((p-1)->tag&&!(f+1)->tag) //下邻块为空闲块{q=f+1;s=q->llink;t=q->rlink;p->llink=s;p->rlink=t;s->rlink=p;t->llink=p;p->size+=q->size;(q+q->size-1)->uplink=p;p->tag=0;}else //上下邻块均为空闲块{s=(p-1)->uplink;t=f+1;s->size+=n+t->size;t->llink->rlink=t->rlink;t->rlink->llink=t->llink;(t+t->size-1)->uplink=s;}}//Free_BT,该算法在课本里有详细的描述.8.14void Free_BS(freelist &avail,char *addr,int n)//伙伴系统的空闲块回收算法{buddy=addr%(2*n)?(addr-n):(addr+n); //求回收块的伙伴地址addr->tag=0;addr->kval=n;for(i=0;avail[i].nodesize<n;i++); //找到这一大小的空闲块链if(!avail[i].first) //尚没有该大小的空闲块{addr->llink=addr;addr->rlink=addr;avail[i].first=addr; //作为唯一一个该大小的空闲块}else{for(p=avail[i].first;p!=buddy&&p!=avail[i].first;p=p->rlink);//寻找伙伴 if(p==buddy) //伙伴为空闲块,此时进行合并{if(p->rlink==p) avail[i].first=NULL;//伙伴是此大小的唯一空闲块else{p->llink->rlink=p->rlink;p->rlink->llink=p->llink;} //从空闲块链中删去伙伴new=addr>p?p:addr; //合并后的新块首址Free_BS(avail,new,2*n); //递归地回收新块}//ifelse //伙伴为占用块,此时插入空闲块链头部{q=p->rlink;p->rlink=addr;addr->llink=p;q->llink=addr;addr->rlink=q;}}//else}//Free_BS8.15FBList *MakeList(char *highbound,char *lowbound)//把堆结构存储的的所有空闲块链接成可利用空间表,并返回表头指针{p=lowbound;while(p->tag&&p<highbound) p++; //查找第一个空闲块if(p>=highbound) return NULL; //没有空闲块head=p;for(q=p;p<highbound;p+=cellsize) //建立链表if(!p->tag){q->next=p;q=p;}//ifp->next=NULL;return head; //返回头指针}//MakeList8.16void Mem_Contract(Heap &H)//对堆H执行存储紧缩{q=MemStart;j=0;for(i=0;i<Max_ListLen;i++)if(H.list[i].stadr->tag){s=H.list[i].length;p=H.list[i].stadr;for(k=0;k<s;k++) *(q++)=*(p++); //紧缩内存空间 H.list[j].stadr=q;H.list[j].length=s; //紧缩占用空间表j++;}}//Mem_Contract。

数据结构课件第8章

数据结构课件第8章
,操作系统中的可利用空间表属于这种类型。 若用户需求量为n,链表中仅有一块其容量m≥n,则分割 出大小为n的部分分配给用户,剩余大小为m-n的部分作为一 个结点留在链表中(只要把size改小就行)。 问题:若空闲块链表中有若干个大小不小于n的结点,该分配 哪一个?分配策略?
三种分配策略:首次拟合法;最佳拟合法;最差拟合法。
存储管理是一个既复杂而又重要的问 题。在后续课程——操作系统和编译技术 (或方法、原理)中,将对其作较深入的 研究。在数据库技术中,也涉及大量有关 存储管理的问题。本章仅就动态存储管理 方面的一些基本技术进行讨论。
返回目录
8.1 概述
● 动态存储管理的基本问题与解决途径 动态存储管理的基本问题
(1) 如何按用户提出的“请示”分配内存? (2) 如何回收那些用户不再使用而“释放”的内存,以 备新的“请示”产生时重新进行分配?
8.2 可利用空间表及分配方法
8.2.1 可利用空间表的结构形式 ● 结构形式二:建立若干个可利用空间表,同一链表中的结点
大小相同。不同链表中的结点大小,一般成倍数关系。
tag type link
示例2 有三种大小结点 (设结点大小分 别为2,4,8个字) 的可利用空间表 的结点结构及其 可利用空间表。
18,000
分配给用户的占用块
1 7,000
8.2 可利用空间表及分配方法
8.2.2 分配策略 ● 最佳拟合法:
从空闲块链表中找出能满足用户请求容 量的最小空闲块。 显然这是一种较好的方法,但为了满足某个请示分配,需要对 空闲块链表从头至尾扫描,时间开销大。 最佳空闲块 示例5 上例,若采用最佳拟合法,则可得
8.2 可利用空间表及分配方法
8.2.2 分配策略 ● 首次拟合法:
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

8.3边界标识法
边界标识法是操作系统中用以进行动态分区分配 的一种存储管理方法,它属于12.2节中介绍的第三种 情况,即用户请求的内存块大小不固定,随不同的请 求而变化。系统将所有的空闲块链接在一个双重循环 链表结构的可利用空间表中;分配可按最先适应分配 算法进行,也可按最优适应分配算法进行。系统的特 点在于:在每个内存区的头部和底部两个边界上分别 设有标识,以识别该区域为占有块或空闲块,使得在 回收用户释放的空闲块时容易判别在物理位臵上与其 相邻的内存区域是否为空闲块,以便将所有地址连续 的空闲存储区组合成一个尽可能大的空闲块。
为方便操作,可利用空间表可组织成双重循环链表。 head中的llink和rlink分别指向链表中的前趋结点和后 继结点,表中不设表头结点,表头指针pav可以指向 表中任一结点,即任何一个结点都可看成是链表中的 第一个结点;表头指针为空则表明可利用空间表为空。
pav
0
1000
0
600
0
2000
0 0
8.4 伙伴系统



是操作系统中用到的另一种动态存储管 理方法。和边界标识法类似。 区别:在伙伴系统中,无论是占用块还 是空闲块,其大小均为2的k次幂。 例如:用户申请n个字的空间时,分配的 块大小为2k个字(2k-1<n<=2k)
8.5无用单元的收集
可利用空间表虽然方便地实现了存储空间的动态管 理,但它的主要特点是应用户的请求而分配内存,在 用户释放存储空间时进行回收。因此,在这类存储管 理系统中,用户必须明确给出“请求”和“释放”的 信息。但用户难免在某些时候会因为疏漏或其它原因 致使系统没有进行回收而产生“无用单元”的问题。 此处,“无用单元”指的是那些用户不再使用而系统 又没有回收的结构或变量。例如,下列C程序段 s=malloc(20); t=malloc(12); …
J0
J1
J2
J3
J4
J5
J6
J7
(A)系统运行初期
可利用空间 块 或空闲块
J0 J2 J3 J5 J7
(B)系统运行若干时间以后
占用块
现在讨论,在图8.1(b)所示的内存状态下,此时又 有新的用户作业进入系统请求分配内存,系统将如何 处理? 通常有两种做法:一种策略是系统继续从高地址的空 闲块中进行分配,而不理会已分配给用户的内存是否 已空闲,直到分配无法进行
若释放块的左、右邻区均为占用块,则处理最为简 单,只要将此新的空闲块作为一个结点插入到可利用 空间表中即可;若只有左邻区是空闲块,则应将回收 块与其左邻区合并成一个结点;若只有右邻区是空闲 块,则应将回收块与其右邻区合并成一个结点;若左、 右邻区都是空闲块,则应将三块合起来成为一个结点 留在可利用空间表中。
tag
size space
link
0 空闲块
tag=
1 占用块
由于可利用空间表中的结点大小不同,因此相应 的分配与回收过程较为复杂。假设某用户需大小为n 的内存,而可利用空间表中仅有一块大小为m≥n的空 闲块,则只需将其中大小为n的一部分分配给申请的 用户,同时将剩余大小为m-n的部分作为一个结点留 在链表中即可。当可利用空间表中存在多个空间大小 不小于n的空闲块时,一般可采用以下三种不同的分 配策略。
用户作业;反之,只分配其中n个字的内存块。同时, 为了避免修改指针,在分配部分空间时约定将结点中 的高地址部分分配给用户。 (2)按照最先适应分配策略,每次在分配存储块时 总是从表头指针pav所指的结点开始进行查找,找到 第一不小于n的空闲块即进行分配。但是,由于每次 总是从同一个结点开始查找,必然造成存储容量小 的结点集中在链表的前端,这同样会增加查找较大 空闲块的时间。因此,在每次分配完成之后,令指 针pav指向刚进行分配的结点的后继结点,这就是为 何将可利用空间表组织成循环链表的原因。
由于表中结点大小相同,所以在分配时无需查找,只 要将第一个结点分配给用户即可;同样,当用户程序 释放内存时,系统只需将用户释放的空闲块插入在表 头即可。这种情况下的可利用空间表实质上是一个链 栈,对应的存储管理方式在操作系统中称为“固定分 区管理”。 第二种情况是系统运行期间用户请求分配的存储量有 若干大小的固定规格。 对此系统,可将用户存储空间分割成不同规格的若干 块,并将大小相同的空闲块组织在同一个可利用空间 表中,即同一链表中的结点大小相同。
0
8.3.2分配算法
本节以最先适应分配算法来说明边界标识法的应 用。实现时,可以从表头指针pav所指的第一个结点 开始进行查询,找到第一个容量不小于请求分配的 存储量的空闲块即可进行分配。为了使整个系统更 有效地运行,在边界标识法中可做如下两条约定:
(1)假设找到的某个待分配的空闲块的容量为m个 字,若每次只从中分配n(n<m)个字给用户作业, 则剩余m-n个字大小的空闲块结点仍留在链表中。如 此进行多次分配之后,链表中会出现一些容量极小称 之为“碎片”的空闲块,这样将大大减慢分配(查找) 的速度。为克服这一弊端,可以选定一个适当的容量 e,当m-n<e时,就将容量为m的空闲块整块分配给
上述三种分配方法的选取一般需要考虑以下因素: 用户的逻辑要求;请求分配量的大小分布;分配和释 放的频率以及效率对系统的重要性等。 无论采用何种分配方法在进行回收系统空闲块时 需要考虑“结点合并”的问题,即当系统在不断进行 分配和回收的过程中,大的空闲块逐渐被分割成小的 占用块,当用户程序将某一占用块释放重新成为空闲 块时,如果将它作为一个独立的空闲块插入到链表中, 将出现两个或多个地址相邻的空闲块作为几个结点独 立放在可利用空间表中,显然这不利于以后出现的大 容量作业的请求。为了更有效地利用内存,就要求系 统在回收时应考虑将地址相邻的空闲块合并成尽可能 大的结点。
因此,要及时释放共享结点所占的空间,必须给 每个结点增设一个共享计数器,记录本结点被几个链 共享,当结点从某一链中被删除时,就将此计数器减 1,反之在插入时计数器加1,一旦该计数器被减到0 时,说明该结点在结构中不再有用,便可以回收。 这种处理方法的缺点是增加了额外的存储开销, 同时也使程序的处理变得更加复杂。有时少量无用单 元的存在并不会影响系统的正常运行,但是当无用单 元积累到一定阶段,就要求系统去找出这些无用单元, 并把它们送回到可利用空间表中去。在这里关键的问 题是如何从整个存储空间中找出那些无用单元。
s=t; 执行的结果是使执行s=malloc(20)为用户分配的结 点成为无用单元,无法得到使用。
另外,由于数据结构本身的原因也有可能造成无用单 元的产生,如广义表中存在着共享和递归成份,对共 享结点来说,当该结点从某一条链上删除时它可能还 链接在别的关系中,并不能立即释放该结点的空间, 所以只有在全部链接关系中都被删除时,该结点才是 无用结点,该结点所占用的空间才成为无用单元可以 回收。
第8章 动态存储管理
概述
可利用空间表及分配方法 边界标识法 无用单元的收集 存储压缩
存储管理是操作系统的重要组成部分,它负责 管理计算机系统的存储器。 动态存储管理的基本问题是系统如何应用户提 出的“请求”分配内存?又如何收回那些用户不再 使用而释放的内存以备新的“请求”产生时重新进 行分配。本章简单介绍数据结构在动态存储管理中 的一些常用技术,包括可利用空间表及分配方法、 边界标识法、无用单元的收集和压缩存储等内容。
0 10000 20000 28000 32000 55000 99999
起始地址 内存块大小 使用情况
10000 10000 空闲
28000
55000
4000
45000
空闲
空闲
av
0 10000 10000 0 28000 4000 0 55000 45000 ^
(c)链表
8.2可利用空间表及分配方法
(1)最先适应分配算法,这种方法又称为首次适配 法。每次分配时,总是顺序查找可利用空间链表,找 到第一个能满足长度要求的空闲区为止。分割这个找 到的未分配区,一部分分配给作业,另一部分仍为空 闲区。 (2)最优适应分配算法。这种分配算法每次从空闲 区中挑选一个能满足作业要求的最小分区,这样可保 证不去分割一个更大的区域,使装入大作业比较容易 得到满足。 (3)最坏适应分配算法。最坏适应分配算法总是挑 选一个能满足作业要求的最大的空闲区分割给作业 使用,这样可使剩下的空闲区不至于太小,这种算 法对中、小作业是有利的。
另一种策略是用户程序一旦运行结束,便将它所占内 存区释放成为空闲块,同时,每当新的用户请求分配 内存时,系统需要巡视整个内存区中所有空闲块,并 从中找出一个“合适”的空闲块分配之。
为了实现这种分配策略,系统需建立一张记录所有空 闲块的可利用空间表。此表的结构可以是目录表也可 以是链表。如图12.2所示为某系统运行过程中的内存 状态及其两种结构的可利用空间表。
例如,对图8.6所示的可利用空间表进行分配一个大 小为500个字的存储单元后可利用空间表的状态如图 8.7所示,此时,表头指针pav指向了下一个结点。
pav pav
分配500个字
0
500 1000
0
600
0
2000
0
0
0
0
8.3.3回收算法
当用户释放占用块,系统需立即回收以备新的 请求产生时进行再分配。为了使物理地址毗邻的空 闲块结合成一个尽可能大的结点,首先需要检查刚 释放的占用块的左、右紧邻是否为空闲块。采用边 界标识法实现动态存储管理时每个内存区(无论是 占用块或空闲块)的边界上都设有标志值,因此很 容易区分刚释放的占用块的左、右紧邻是否为空闲 块或占用块。
操作系统既可借助目录表结构也可借助链表结构 实现动态存储分配,本节将对采用链表的情况进行 讨论。 根据系统运行的不同情况,可利用空间表可以有 三种不同的结构形式: 第一种情况是系统运行期间所有用户请求分配的存 储量大小相同。对此类系统,可以在系统开始运行 时将内存的用户区域按所需大小分割成若干大小相 同的块,然后用指针链接成一个可利用空间表。
相关文档
最新文档